android: Update app-specific/MIME type icons
[LibreOffice.git] / slideshow / source / engine / eventmultiplexer.cxx
blob80c4c13d9f466e1ec0ada1efa3cfe6c0743617d4
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <comphelper/diagnose_ex.hxx>
23 #include <rtl/ref.hxx>
24 #include <comphelper/compbase.hxx>
26 #include <com/sun/star/awt/XMouseListener.hpp>
27 #include <com/sun/star/awt/XMouseMotionListener.hpp>
28 #include <com/sun/star/presentation/XSlideShowView.hpp>
30 #include <basegfx/matrix/b2dhommatrix.hxx>
31 #include <basegfx/numeric/ftools.hxx>
32 #include <basegfx/point/b2dpoint.hxx>
34 #include <eventqueue.hxx>
35 #include <eventmultiplexer.hxx>
36 #include <listenercontainer.hxx>
37 #include <delayevent.hxx>
38 #include <unoview.hxx>
39 #include <unoviewcontainer.hxx>
41 #include <functional>
42 #include <memory>
43 #include <algorithm>
44 #include <type_traits>
45 #include <utility>
46 #include <vector>
48 using namespace ::com::sun::star;
50 namespace
52 // add operator== for weak_ptr, so we can use std::find over lists of them
53 struct ViewEventHandlerWeakPtrWrapper final {
54 slideshow::internal::ViewEventHandlerWeakPtr ptr;
56 ViewEventHandlerWeakPtrWrapper(slideshow::internal::ViewEventHandlerWeakPtr thePtr):
57 ptr(std::move(thePtr)) {}
59 bool operator ==(ViewEventHandlerWeakPtrWrapper const & other) const
60 { return ptr.lock().get() == other.ptr.lock().get(); }
64 // Needed by ImplViewHandlers; see the ListenerOperations<std::weak_ptr<ListenerTargetT>> partial
65 // specialization in slideshow/source/inc/listenercontainer.hxx:
66 template<>
67 struct slideshow::internal::ListenerOperations<ViewEventHandlerWeakPtrWrapper>
69 template< typename ContainerT,
70 typename FuncT >
71 static bool notifySingleListener( ContainerT& rContainer,
72 FuncT func )
74 for( const auto& rCurr : rContainer )
76 std::shared_ptr<ViewEventHandler> pListener( rCurr.ptr.lock() );
78 if( pListener && func(pListener) )
79 return true;
82 return false;
85 template< typename ContainerT,
86 typename FuncT >
87 static bool notifyAllListeners( ContainerT& rContainer,
88 FuncT func )
90 bool bRet(false);
91 for( const auto& rCurr : rContainer )
93 std::shared_ptr<ViewEventHandler> pListener( rCurr.ptr.lock() );
95 if( pListener.get() &&
96 FunctionApply<typename ::std::invoke_result<FuncT, std::shared_ptr<ViewEventHandler> const&>::type,
97 std::shared_ptr<ViewEventHandler> >::apply(func,pListener) )
99 bRet = true;
103 return bRet;
105 template< typename ContainerT >
106 static void pruneListeners( ContainerT& rContainer,
107 size_t nSizeThreshold )
109 if( rContainer.size() <= nSizeThreshold )
110 return;
112 ContainerT aAliveListeners;
113 aAliveListeners.reserve(rContainer.size());
115 for( const auto& rCurr : rContainer )
117 if( !rCurr.ptr.expired() )
118 aAliveListeners.push_back( rCurr );
121 std::swap( rContainer, aAliveListeners );
125 namespace slideshow::internal {
127 namespace {
129 template <typename HandlerT>
130 class PrioritizedHandlerEntry
132 typedef std::shared_ptr<HandlerT> HandlerSharedPtrT;
133 HandlerSharedPtrT mpHandler;
134 double mnPrio;
136 public:
137 PrioritizedHandlerEntry( HandlerSharedPtrT pHandler,
138 double nPrio ) :
139 mpHandler(std::move(pHandler)),
140 mnPrio(nPrio)
143 HandlerSharedPtrT const& getHandler() const { return mpHandler; }
145 /// To sort according to priority
146 bool operator<( PrioritizedHandlerEntry const& rRHS ) const
148 // reversed order - high prioritized entries
149 // should be at the beginning of the queue
150 return mnPrio > rRHS.mnPrio;
153 /// To permit std::remove in removeHandler template
154 bool operator==( PrioritizedHandlerEntry const& rRHS ) const
156 // ignore prio, for removal, only the handler ptr matters
157 return mpHandler == rRHS.mpHandler;
163 typedef comphelper::WeakComponentImplHelper<
164 awt::XMouseListener,
165 awt::XMouseMotionListener > Listener_UnoBase;
167 namespace {
169 /** Listener class, to decouple UNO lifetime from EventMultiplexer
171 This class gets registered as the XMouse(Motion)Listener on the
172 XSlideViews, and passes on the events to the EventMultiplexer (via
173 EventQueue indirection, to force the events into the main thread)
175 class EventMultiplexerListener : public Listener_UnoBase
177 public:
178 EventMultiplexerListener( EventQueue& rEventQueue,
179 EventMultiplexerImpl& rEventMultiplexer ) :
180 mpEventQueue( &rEventQueue ),
181 mpEventMultiplexer( &rEventMultiplexer )
185 EventMultiplexerListener( const EventMultiplexerListener& ) = delete;
186 EventMultiplexerListener& operator=( const EventMultiplexerListener& ) = delete;
188 // WeakComponentImplHelperBase::disposing
189 virtual void disposing(std::unique_lock<std::mutex>& rGuard) override;
191 private:
192 virtual void SAL_CALL disposing( const lang::EventObject& Source ) override;
194 // XMouseListener implementation
195 virtual void SAL_CALL mousePressed( const awt::MouseEvent& e ) override;
196 virtual void SAL_CALL mouseReleased( const awt::MouseEvent& e ) override;
197 virtual void SAL_CALL mouseEntered( const awt::MouseEvent& e ) override;
198 virtual void SAL_CALL mouseExited( const awt::MouseEvent& e ) override;
200 // XMouseMotionListener implementation
201 virtual void SAL_CALL mouseDragged( const awt::MouseEvent& e ) override;
202 virtual void SAL_CALL mouseMoved( const awt::MouseEvent& e ) override;
205 EventQueue* mpEventQueue;
206 EventMultiplexerImpl* mpEventMultiplexer;
211 struct EventMultiplexerImpl
213 EventMultiplexerImpl( EventQueue& rEventQueue,
214 UnoViewContainer const& rViewContainer ) :
215 mrEventQueue(rEventQueue),
216 mrViewContainer(rViewContainer),
217 mxListener( new EventMultiplexerListener(rEventQueue,
218 *this) ),
219 maNextEffectHandlers(),
220 maSlideStartHandlers(),
221 maSlideEndHandlers(),
222 maAnimationStartHandlers(),
223 maAnimationEndHandlers(),
224 maSlideAnimationsEndHandlers(),
225 maAudioStoppedHandlers(),
226 maCommandStopAudioHandlers(),
227 maPauseHandlers(),
228 maViewHandlers(),
229 maViewRepaintHandlers(),
230 maShapeListenerHandlers(),
231 maUserPaintEventHandlers(),
232 maMouseClickHandlers(),
233 maMouseDoubleClickHandlers(),
234 maMouseMoveHandlers(),
235 maHyperlinkHandlers(),
236 mnTimeout(0.0),
237 mpTickEvent(),
238 mbIsAutoMode(false)
241 ~EventMultiplexerImpl()
243 if( mxListener.is() )
244 mxListener->dispose();
247 /// Remove all handlers
248 void clear();
250 // actual handler callbacks (get called from the UNO interface
251 // listeners via event queue)
252 void mousePressed( const awt::MouseEvent& e );
253 void mouseReleased( const awt::MouseEvent& e );
254 void mouseDragged( const awt::MouseEvent& e );
255 void mouseMoved( const awt::MouseEvent& e );
257 bool isMouseListenerRegistered() const;
259 typedef ThreadUnsafeListenerContainer<
260 PrioritizedHandlerEntry<EventHandler>,
261 std::vector<
262 PrioritizedHandlerEntry<EventHandler> > > ImplNextEffectHandlers;
263 typedef PrioritizedHandlerEntry<MouseEventHandler> ImplMouseHandlerEntry;
264 typedef ThreadUnsafeListenerContainer<
265 ImplMouseHandlerEntry,
266 std::vector<ImplMouseHandlerEntry> > ImplMouseHandlers;
267 typedef ThreadUnsafeListenerContainer<
268 EventHandlerSharedPtr,
269 std::vector<EventHandlerSharedPtr> > ImplEventHandlers;
270 typedef ThreadUnsafeListenerContainer<
271 AnimationEventHandlerSharedPtr,
272 std::vector<AnimationEventHandlerSharedPtr> > ImplAnimationHandlers;
273 typedef ThreadUnsafeListenerContainer<
274 PauseEventHandlerSharedPtr,
275 std::vector<PauseEventHandlerSharedPtr> > ImplPauseHandlers;
276 typedef ThreadUnsafeListenerContainer<
277 ViewEventHandlerWeakPtrWrapper,
278 std::vector<ViewEventHandlerWeakPtrWrapper> > ImplViewHandlers;
279 typedef ThreadUnsafeListenerContainer<
280 ViewRepaintHandlerSharedPtr,
281 std::vector<ViewRepaintHandlerSharedPtr> > ImplRepaintHandlers;
282 typedef ThreadUnsafeListenerContainer<
283 ShapeListenerEventHandlerSharedPtr,
284 std::vector<ShapeListenerEventHandlerSharedPtr> > ImplShapeListenerHandlers;
285 typedef ThreadUnsafeListenerContainer<
286 UserPaintEventHandlerSharedPtr,
287 std::vector<UserPaintEventHandlerSharedPtr> > ImplUserPaintEventHandlers;
288 typedef ThreadUnsafeListenerContainer<
289 PrioritizedHandlerEntry<HyperlinkHandler>,
290 std::vector<PrioritizedHandlerEntry<HyperlinkHandler> > > ImplHyperLinkHandlers;
292 template <typename XSlideShowViewFunc>
293 void forEachView( XSlideShowViewFunc pViewMethod );
295 UnoViewSharedPtr findUnoView(const uno::Reference<
296 presentation::XSlideShowView>& xView) const;
298 template< typename RegisterFunction >
299 void addMouseHandler( ImplMouseHandlers& rHandlerContainer,
300 const MouseEventHandlerSharedPtr& rHandler,
301 double nPriority,
302 RegisterFunction pRegisterListener );
304 static bool notifyAllAnimationHandlers( ImplAnimationHandlers const& rContainer,
305 AnimationNodeSharedPtr const& rNode );
307 bool notifyMouseHandlers(
308 const ImplMouseHandlers& rQueue,
309 bool (MouseEventHandler::*pHandlerMethod)(
310 const awt::MouseEvent& ),
311 const awt::MouseEvent& e );
313 bool notifyNextEffect();
315 /// Called for automatic nextEffect
316 void tick();
318 /// Schedules a tick event
319 void scheduleTick();
321 /// Schedules tick events, if mbIsAutoMode is true
322 void handleTicks();
324 basegfx::B2DPoint toMatrixPoint(uno::Reference<presentation::XSlideShowView> xView,
325 basegfx::B2DPoint pnt);
326 basegfx::B2DPoint toNormalPoint(uno::Reference<presentation::XSlideShowView> xView,
327 basegfx::B2DPoint pnt);
329 EventQueue& mrEventQueue;
330 UnoViewContainer const& mrViewContainer;
331 ::rtl::Reference<
332 EventMultiplexerListener> mxListener;
334 ImplNextEffectHandlers maNextEffectHandlers;
335 ImplEventHandlers maSlideStartHandlers;
336 ImplEventHandlers maSlideEndHandlers;
337 ImplAnimationHandlers maAnimationStartHandlers;
338 ImplAnimationHandlers maAnimationEndHandlers;
339 ImplEventHandlers maSlideAnimationsEndHandlers;
340 ImplAnimationHandlers maAudioStoppedHandlers;
341 ImplAnimationHandlers maCommandStopAudioHandlers;
342 ImplPauseHandlers maPauseHandlers;
343 ImplViewHandlers maViewHandlers;
344 ImplRepaintHandlers maViewRepaintHandlers;
345 ImplShapeListenerHandlers maShapeListenerHandlers;
346 ImplUserPaintEventHandlers maUserPaintEventHandlers;
347 ImplMouseHandlers maMouseClickHandlers;
348 ImplMouseHandlers maMouseDoubleClickHandlers;
349 ImplMouseHandlers maMouseMoveHandlers;
350 ImplHyperLinkHandlers maHyperlinkHandlers;
352 /// automatic next effect mode timeout
353 double mnTimeout;
355 /** Holds ptr to optional tick event weakly
357 When event queue is cleansed, the next
358 setAutomaticMode(true) call is then able to
359 regenerate the event.
361 ::std::weak_ptr< Event > mpTickEvent;
362 bool mbIsAutoMode;
366 void EventMultiplexerListener::disposing(std::unique_lock<std::mutex>& /*rGuard*/)
368 mpEventQueue = nullptr;
369 mpEventMultiplexer = nullptr;
372 void SAL_CALL EventMultiplexerListener::disposing(
373 const lang::EventObject& /*rSource*/ )
375 // there's no real point in acting on this message - after all,
376 // the event sources are the XSlideShowViews, which must be
377 // explicitly removed from the slideshow via
378 // XSlideShow::removeView(). thus, if a XSlideShowView has
379 // properly removed itself from the slideshow, it will not be
380 // found here. and if it hasn't, there'll be other references at
381 // other places within the slideshow, anyway...
384 void SAL_CALL EventMultiplexerListener::mousePressed(
385 const awt::MouseEvent& e )
387 std::unique_lock const guard( m_aMutex );
389 // notify mouse press. Don't call handlers directly, this
390 // might not be the main thread!
391 if( mpEventQueue )
392 mpEventQueue->addEvent(
393 makeEvent( std::bind( &EventMultiplexerImpl::mousePressed,
394 mpEventMultiplexer,
395 e ),
396 "EventMultiplexerImpl::mousePressed") );
399 void SAL_CALL EventMultiplexerListener::mouseReleased(
400 const awt::MouseEvent& e )
402 std::unique_lock const guard( m_aMutex );
404 // notify mouse release. Don't call handlers directly,
405 // this might not be the main thread!
406 if( mpEventQueue )
407 mpEventQueue->addEvent(
408 makeEvent( std::bind( &EventMultiplexerImpl::mouseReleased,
409 mpEventMultiplexer,
410 e ),
411 "EventMultiplexerImpl::mouseReleased") );
414 void SAL_CALL EventMultiplexerListener::mouseEntered(
415 const awt::MouseEvent& /*e*/ )
417 // not used here
420 void SAL_CALL EventMultiplexerListener::mouseExited(
421 const awt::MouseEvent& /*e*/ )
423 // not used here
426 // XMouseMotionListener implementation
427 void SAL_CALL EventMultiplexerListener::mouseDragged(
428 const awt::MouseEvent& e )
430 std::unique_lock const guard( m_aMutex );
432 // notify mouse drag. Don't call handlers directly, this
433 // might not be the main thread!
434 if( mpEventQueue )
435 mpEventQueue->addEvent(
436 makeEvent( std::bind( &EventMultiplexerImpl::mouseDragged,
437 mpEventMultiplexer,
438 e ),
439 "EventMultiplexerImpl::mouseDragged") );
442 void SAL_CALL EventMultiplexerListener::mouseMoved(
443 const awt::MouseEvent& e )
445 std::unique_lock const guard( m_aMutex );
447 // notify mouse move. Don't call handlers directly, this
448 // might not be the main thread!
449 if( mpEventQueue )
450 mpEventQueue->addEvent(
451 makeEvent( std::bind( &EventMultiplexerImpl::mouseMoved,
452 mpEventMultiplexer,
453 e ),
454 "EventMultiplexerImpl::mouseMoved") );
458 bool EventMultiplexerImpl::notifyAllAnimationHandlers( ImplAnimationHandlers const& rContainer,
459 AnimationNodeSharedPtr const& rNode )
461 return rContainer.applyAll(
462 [&rNode]( const AnimationEventHandlerSharedPtr& pEventHandler )
463 { return pEventHandler->handleAnimationEvent( rNode ); } );
466 template <typename XSlideShowViewFunc>
467 void EventMultiplexerImpl::forEachView( XSlideShowViewFunc pViewMethod )
469 if( !pViewMethod )
470 return;
472 // (un)register mouse listener on all views
473 for( UnoViewVector::const_iterator aIter( mrViewContainer.begin() ),
474 aEnd( mrViewContainer.end() ); aIter != aEnd; ++aIter )
476 uno::Reference<presentation::XSlideShowView> xView ((*aIter)->getUnoView());
477 if (xView.is())
479 (xView.get()->*pViewMethod)( mxListener.get() );
481 else
483 OSL_ASSERT(xView.is());
488 UnoViewSharedPtr EventMultiplexerImpl::findUnoView(
489 const uno::Reference<presentation::XSlideShowView>& xView) const
491 // find view from which the change originated
492 UnoViewVector::const_iterator aIter;
493 const UnoViewVector::const_iterator aEnd ( mrViewContainer.end() );
494 if( (aIter=std::find_if( mrViewContainer.begin(),
495 aEnd,
496 [&xView]( const UnoViewSharedPtr& pView )
497 { return xView == pView->getUnoView(); } )) == aEnd )
499 OSL_FAIL("EventMultiplexer::findUnoView(): unexpected message source" );
500 return UnoViewSharedPtr();
503 return *aIter;
506 template< typename RegisterFunction >
507 void EventMultiplexerImpl::addMouseHandler(
508 ImplMouseHandlers& rHandlerContainer,
509 const MouseEventHandlerSharedPtr& rHandler,
510 double nPriority,
511 RegisterFunction pRegisterListener )
513 ENSURE_OR_THROW(
514 rHandler,
515 "EventMultiplexer::addMouseHandler(): Invalid handler" );
517 // register mouse listener on all views
518 forEachView( pRegisterListener );
520 // add into sorted container:
521 rHandlerContainer.addSorted(
522 typename ImplMouseHandlers::container_type::value_type(
523 rHandler,
524 nPriority ));
527 bool EventMultiplexerImpl::isMouseListenerRegistered() const
529 return !(maMouseClickHandlers.isEmpty() &&
530 maMouseDoubleClickHandlers.isEmpty());
533 void EventMultiplexerImpl::tick()
535 if( !mbIsAutoMode )
536 return; // this event is just a left-over, ignore
538 notifyNextEffect();
540 if( !maNextEffectHandlers.isEmpty() )
542 // still handlers left, schedule next timeout
543 // event. Will also set mbIsTickEventOn back to true
544 scheduleTick();
548 void EventMultiplexerImpl::scheduleTick()
550 EventSharedPtr pEvent(
551 makeDelay( [this] () { this->tick(); },
552 mnTimeout,
553 "EventMultiplexerImpl::tick with delay"));
555 // store weak reference to generated event, to notice when
556 // the event queue gets cleansed (we then have to
557 // regenerate the tick event!)
558 mpTickEvent = pEvent;
560 // enabled auto mode: simply schedule a timeout event,
561 // which will eventually call our tick() method
562 mrEventQueue.addEventForNextRound( pEvent );
565 void EventMultiplexerImpl::handleTicks()
567 if( !mbIsAutoMode )
568 return; // nothing to do, don't need no ticks
570 EventSharedPtr pTickEvent( mpTickEvent.lock() );
571 if( pTickEvent )
572 return; // nothing to do, there's already a tick
573 // pending
575 // schedule initial tick (which reschedules itself
576 // after that, all by itself)
577 scheduleTick();
580 basegfx::B2DPoint
581 EventMultiplexerImpl::toNormalPoint(uno::Reference<presentation::XSlideShowView> xView,
582 basegfx::B2DPoint pnt)
584 UnoViewVector::const_iterator aIter;
585 const UnoViewVector::const_iterator aEnd(mrViewContainer.end());
586 if ((aIter = std::find_if(
587 mrViewContainer.begin(), aEnd,
588 [&xView](const UnoViewSharedPtr& pView) { return xView == pView->getUnoView(); }))
589 == aEnd)
591 return pnt;
594 basegfx::B2DPoint aPosition(pnt.getX(), pnt.getY());
595 basegfx::B2DHomMatrix aMatrix((*aIter)->getTransformation());
596 aPosition *= aMatrix;
598 aPosition.setX(basegfx::fround(aPosition.getX()));
599 aPosition.setY(basegfx::fround(aPosition.getY()));
600 return aPosition;
603 basegfx::B2DPoint
604 EventMultiplexerImpl::toMatrixPoint(uno::Reference<presentation::XSlideShowView> xView,
605 basegfx::B2DPoint pnt)
607 UnoViewVector::const_iterator aIter;
608 const UnoViewVector::const_iterator aEnd(mrViewContainer.end());
609 if ((aIter = std::find_if(
610 mrViewContainer.begin(), aEnd,
611 [&xView](const UnoViewSharedPtr& pView) { return xView == pView->getUnoView(); }))
612 == aEnd)
614 return pnt;
617 basegfx::B2DPoint aPosition(pnt.getX(), pnt.getY());
618 basegfx::B2DHomMatrix aMatrix((*aIter)->getTransformation());
619 if (!aMatrix.invert())
620 ENSURE_OR_THROW(false, "EventMultiplexer::notifyHandlers():"
621 " view matrix singular");
622 aPosition *= aMatrix;
624 aPosition.setX(basegfx::fround(aPosition.getX()));
625 aPosition.setY(basegfx::fround(aPosition.getY()));
626 return aPosition;
629 void EventMultiplexerImpl::clear()
631 // deregister from all views.
632 if( isMouseListenerRegistered() )
634 for( UnoViewVector::const_iterator aIter=mrViewContainer.begin(),
635 aEnd=mrViewContainer.end();
636 aIter!=aEnd;
637 ++aIter )
639 if( (*aIter)->getUnoView().is() )
640 (*aIter)->getUnoView()->removeMouseListener( mxListener );
644 if( !maMouseMoveHandlers.isEmpty() )
646 for( UnoViewVector::const_iterator aIter=mrViewContainer.begin(),
647 aEnd=mrViewContainer.end();
648 aIter!=aEnd;
649 ++aIter )
651 if( (*aIter)->getUnoView().is() )
652 (*aIter)->getUnoView()->removeMouseMotionListener( mxListener );
656 // clear all handlers (releases all references)
657 maNextEffectHandlers.clear();
658 maSlideStartHandlers.clear();
659 maSlideEndHandlers.clear();
660 maAnimationStartHandlers.clear();
661 maAnimationEndHandlers.clear();
662 maSlideAnimationsEndHandlers.clear();
663 maAudioStoppedHandlers.clear();
664 maCommandStopAudioHandlers.clear();
665 maPauseHandlers.clear();
666 maViewHandlers.clear();
667 maViewRepaintHandlers.clear();
668 maMouseClickHandlers.clear();
669 maMouseDoubleClickHandlers.clear();
670 maMouseMoveHandlers.clear();
671 maHyperlinkHandlers.clear();
672 mpTickEvent.reset();
675 // XMouseListener implementation
676 bool EventMultiplexerImpl::notifyMouseHandlers(
677 const ImplMouseHandlers& rQueue,
678 bool (MouseEventHandler::*pHandlerMethod)( const awt::MouseEvent& ),
679 const awt::MouseEvent& e )
681 uno::Reference<presentation::XSlideShowView> xView(
682 e.Source, uno::UNO_QUERY );
684 ENSURE_OR_RETURN_FALSE( xView.is(), "EventMultiplexer::notifyHandlers(): "
685 "event source is not an XSlideShowView" );
687 // find corresponding view (to map mouse position into user
688 // coordinate space)
689 UnoViewVector::const_iterator aIter;
690 const UnoViewVector::const_iterator aEnd ( mrViewContainer.end() );
691 if( (aIter=::std::find_if(
692 mrViewContainer.begin(),
693 aEnd,
694 [&xView]( const UnoViewSharedPtr& pView )
695 { return xView == pView->getUnoView(); } )) == aEnd )
697 ENSURE_OR_RETURN_FALSE(
698 false, "EventMultiplexer::notifyHandlers(): "
699 "event source not found under registered views" );
702 // convert mouse position to user coordinate space
703 ::basegfx::B2DPoint aPosition( e.X, e.Y );
704 ::basegfx::B2DHomMatrix aMatrix( (*aIter)->getTransformation() );
705 if( !aMatrix.invert() )
706 ENSURE_OR_THROW( false, "EventMultiplexer::notifyHandlers():"
707 " view matrix singular" );
708 aPosition *= aMatrix;
710 awt::MouseEvent aEvent( e );
711 aEvent.X = ::basegfx::fround( aPosition.getX() );
712 aEvent.Y = ::basegfx::fround( aPosition.getY() );
714 // fire event on handlers, try in order of precedence. If
715 // one high-priority handler rejects the event
716 // (i.e. returns false), try next handler.
717 return rQueue.apply(
718 [&pHandlerMethod, &aEvent]( const ImplMouseHandlerEntry& rMouseHandler )
719 { return ( ( *rMouseHandler.getHandler() ).*pHandlerMethod )( aEvent ); } );
722 void EventMultiplexerImpl::mousePressed( const awt::MouseEvent& e )
724 // fire double-click events for every second click
725 sal_Int32 nCurrClickCount = e.ClickCount;
726 while( nCurrClickCount > 1 &&
727 notifyMouseHandlers( maMouseDoubleClickHandlers,
728 &MouseEventHandler::handleMousePressed,
729 e ))
731 nCurrClickCount -= 2;
734 // fire single-click events for all remaining clicks
735 while( nCurrClickCount > 0 &&
736 notifyMouseHandlers( maMouseClickHandlers,
737 &MouseEventHandler::handleMousePressed,
738 e ))
740 --nCurrClickCount;
744 void EventMultiplexerImpl::mouseReleased( const awt::MouseEvent& e )
746 // fire double-click events for every second click
747 sal_Int32 nCurrClickCount = e.ClickCount;
748 while( nCurrClickCount > 1 &&
749 notifyMouseHandlers( maMouseDoubleClickHandlers,
750 &MouseEventHandler::handleMouseReleased,
751 e ))
753 nCurrClickCount -= 2;
756 // fire single-click events for all remaining clicks
757 while( nCurrClickCount > 0 &&
758 notifyMouseHandlers( maMouseClickHandlers,
759 &MouseEventHandler::handleMouseReleased,
760 e ))
762 --nCurrClickCount;
766 void EventMultiplexerImpl::mouseDragged( const awt::MouseEvent& e )
768 notifyMouseHandlers( maMouseMoveHandlers,
769 &MouseEventHandler::handleMouseDragged,
770 e );
773 void EventMultiplexerImpl::mouseMoved( const awt::MouseEvent& e )
775 notifyMouseHandlers( maMouseMoveHandlers,
776 &MouseEventHandler::handleMouseMoved,
777 e );
780 bool EventMultiplexerImpl::notifyNextEffect()
782 // fire event on handlers, try in order of precedence. If one
783 // high-priority handler rejects the event (i.e. returns false),
784 // try next handler.
785 return maNextEffectHandlers.apply(
786 []( const PrioritizedHandlerEntry< EventHandler >& pHandler )
787 { return pHandler.getHandler()->handleEvent(); } );
791 EventMultiplexer::EventMultiplexer( EventQueue& rEventQueue,
792 UnoViewContainer const& rViewContainer ) :
793 mpImpl( new EventMultiplexerImpl(rEventQueue, rViewContainer) )
797 EventMultiplexer::~EventMultiplexer()
799 // outline because of EventMultiplexerImpl's incomplete type
802 void EventMultiplexer::clear()
804 mpImpl->clear();
807 void EventMultiplexer::setAutomaticMode( bool bIsAuto )
809 if( bIsAuto == mpImpl->mbIsAutoMode )
810 return; // no change, nothing to do
812 mpImpl->mbIsAutoMode = bIsAuto;
814 mpImpl->handleTicks();
817 bool EventMultiplexer::getAutomaticMode() const
819 return mpImpl->mbIsAutoMode;
822 void EventMultiplexer::setAutomaticTimeout( double nTimeout )
824 mpImpl->mnTimeout = nTimeout;
827 double EventMultiplexer::getAutomaticTimeout() const
829 return mpImpl->mnTimeout;
832 void EventMultiplexer::addNextEffectHandler(
833 EventHandlerSharedPtr const& rHandler,
834 double nPriority )
836 mpImpl->maNextEffectHandlers.addSorted(
837 EventMultiplexerImpl::ImplNextEffectHandlers::container_type::value_type(
838 rHandler,
839 nPriority) );
841 // Enable tick events, if not done already
842 mpImpl->handleTicks();
845 void EventMultiplexer::removeNextEffectHandler(
846 const EventHandlerSharedPtr& rHandler )
848 mpImpl->maNextEffectHandlers.remove(
849 EventMultiplexerImpl::ImplNextEffectHandlers::container_type::value_type(
850 rHandler,
851 0.0) );
854 void EventMultiplexer::addSlideStartHandler(
855 const EventHandlerSharedPtr& rHandler )
857 mpImpl->maSlideStartHandlers.add( rHandler );
860 void EventMultiplexer::removeSlideStartHandler(
861 const EventHandlerSharedPtr& rHandler )
863 mpImpl->maSlideStartHandlers.remove( rHandler );
866 void EventMultiplexer::addSlideEndHandler(
867 const EventHandlerSharedPtr& rHandler )
869 mpImpl->maSlideEndHandlers.add( rHandler );
872 void EventMultiplexer::removeSlideEndHandler(
873 const EventHandlerSharedPtr& rHandler )
875 mpImpl->maSlideEndHandlers.remove( rHandler );
878 void EventMultiplexer::addAnimationStartHandler(
879 const AnimationEventHandlerSharedPtr& rHandler )
881 mpImpl->maAnimationStartHandlers.add( rHandler );
884 void EventMultiplexer::removeAnimationStartHandler(
885 const AnimationEventHandlerSharedPtr& rHandler )
887 mpImpl->maAnimationStartHandlers.remove( rHandler );
890 void EventMultiplexer::addAnimationEndHandler(
891 const AnimationEventHandlerSharedPtr& rHandler )
893 mpImpl->maAnimationEndHandlers.add( rHandler );
896 void EventMultiplexer::removeAnimationEndHandler(
897 const AnimationEventHandlerSharedPtr& rHandler )
899 mpImpl->maAnimationEndHandlers.remove( rHandler );
902 void EventMultiplexer::addSlideAnimationsEndHandler(
903 const EventHandlerSharedPtr& rHandler )
905 mpImpl->maSlideAnimationsEndHandlers.add( rHandler );
908 void EventMultiplexer::removeSlideAnimationsEndHandler(
909 const EventHandlerSharedPtr& rHandler )
911 mpImpl->maSlideAnimationsEndHandlers.remove( rHandler );
914 void EventMultiplexer::addAudioStoppedHandler(
915 const AnimationEventHandlerSharedPtr& rHandler )
917 mpImpl->maAudioStoppedHandlers.add( rHandler );
920 void EventMultiplexer::removeAudioStoppedHandler(
921 const AnimationEventHandlerSharedPtr& rHandler )
923 mpImpl->maAudioStoppedHandlers.remove( rHandler );
926 void EventMultiplexer::addCommandStopAudioHandler(
927 const AnimationEventHandlerSharedPtr& rHandler )
929 mpImpl->maCommandStopAudioHandlers.add( rHandler );
932 void EventMultiplexer::removeCommandStopAudioHandler(
933 const AnimationEventHandlerSharedPtr& rHandler )
935 mpImpl->maCommandStopAudioHandlers.remove( rHandler );
938 void EventMultiplexer::addPauseHandler(
939 const PauseEventHandlerSharedPtr& rHandler )
941 mpImpl->maPauseHandlers.add( rHandler );
944 void EventMultiplexer::removePauseHandler(
945 const PauseEventHandlerSharedPtr& rHandler )
947 mpImpl->maPauseHandlers.remove( rHandler );
950 void EventMultiplexer::addViewHandler(
951 const ViewEventHandlerWeakPtr& rHandler )
953 mpImpl->maViewHandlers.add( rHandler );
956 void EventMultiplexer::removeViewHandler( const ViewEventHandlerWeakPtr& rHandler )
958 mpImpl->maViewHandlers.remove( rHandler );
961 void EventMultiplexer::addViewRepaintHandler( const ViewRepaintHandlerSharedPtr& rHandler )
963 mpImpl->maViewRepaintHandlers.add( rHandler );
966 void EventMultiplexer::removeViewRepaintHandler( const ViewRepaintHandlerSharedPtr& rHandler )
968 mpImpl->maViewRepaintHandlers.remove( rHandler );
971 void EventMultiplexer::addShapeListenerHandler( const ShapeListenerEventHandlerSharedPtr& rHandler )
973 mpImpl->maShapeListenerHandlers.add( rHandler );
976 void EventMultiplexer::removeShapeListenerHandler( const ShapeListenerEventHandlerSharedPtr& rHandler )
978 mpImpl->maShapeListenerHandlers.remove( rHandler );
981 void EventMultiplexer::addUserPaintHandler( const UserPaintEventHandlerSharedPtr& rHandler )
983 mpImpl->maUserPaintEventHandlers.add( rHandler );
986 void EventMultiplexer::addClickHandler(
987 const MouseEventHandlerSharedPtr& rHandler,
988 double nPriority )
990 mpImpl->addMouseHandler(
991 mpImpl->maMouseClickHandlers,
992 rHandler,
993 nPriority,
994 mpImpl->isMouseListenerRegistered()
995 ? nullptr
996 : &presentation::XSlideShowView::addMouseListener );
999 void EventMultiplexer::removeClickHandler(
1000 const MouseEventHandlerSharedPtr& rHandler )
1002 mpImpl->maMouseClickHandlers.remove(
1003 EventMultiplexerImpl::ImplMouseHandlers::container_type::value_type(
1004 rHandler,
1005 0.0) );
1007 if( !mpImpl->isMouseListenerRegistered() )
1008 mpImpl->forEachView( &presentation::XSlideShowView::removeMouseListener );
1011 void EventMultiplexer::addDoubleClickHandler(
1012 const MouseEventHandlerSharedPtr& rHandler,
1013 double nPriority )
1015 mpImpl->addMouseHandler(
1016 mpImpl->maMouseDoubleClickHandlers,
1017 rHandler,
1018 nPriority,
1019 mpImpl->isMouseListenerRegistered()
1020 ? nullptr
1021 : &presentation::XSlideShowView::addMouseListener );
1024 void EventMultiplexer::removeDoubleClickHandler(
1025 const MouseEventHandlerSharedPtr& rHandler )
1027 mpImpl->maMouseDoubleClickHandlers.remove(
1028 EventMultiplexerImpl::ImplMouseHandlers::container_type::value_type(
1029 rHandler,
1030 0.0) );
1032 if( !mpImpl->isMouseListenerRegistered() )
1033 mpImpl->forEachView( &presentation::XSlideShowView::removeMouseListener );
1036 void EventMultiplexer::addMouseMoveHandler(
1037 const MouseEventHandlerSharedPtr& rHandler,
1038 double nPriority )
1040 mpImpl->addMouseHandler(
1041 mpImpl->maMouseMoveHandlers,
1042 rHandler,
1043 nPriority,
1044 mpImpl->maMouseMoveHandlers.isEmpty()
1045 ? &presentation::XSlideShowView::addMouseMotionListener
1046 : nullptr );
1049 void EventMultiplexer::removeMouseMoveHandler(
1050 const MouseEventHandlerSharedPtr& rHandler )
1052 mpImpl->maMouseMoveHandlers.remove(
1053 EventMultiplexerImpl::ImplMouseHandlers::container_type::value_type(
1054 rHandler,
1055 0.0) );
1057 if( mpImpl->maMouseMoveHandlers.isEmpty() )
1058 mpImpl->forEachView(
1059 &presentation::XSlideShowView::removeMouseMotionListener );
1062 void EventMultiplexer::addHyperlinkHandler( const HyperlinkHandlerSharedPtr& rHandler,
1063 double nPriority )
1065 mpImpl->maHyperlinkHandlers.addSorted(
1066 EventMultiplexerImpl::ImplHyperLinkHandlers::container_type::value_type(
1067 rHandler,
1068 nPriority) );
1071 void EventMultiplexer::removeHyperlinkHandler( const HyperlinkHandlerSharedPtr& rHandler )
1073 mpImpl->maHyperlinkHandlers.remove(
1074 EventMultiplexerImpl::ImplHyperLinkHandlers::container_type::value_type(
1075 rHandler,
1076 0.0) );
1079 void EventMultiplexer::notifyShapeListenerAdded(
1080 const uno::Reference<drawing::XShape>& xShape )
1082 mpImpl->maShapeListenerHandlers.applyAll(
1083 [&xShape]( const ShapeListenerEventHandlerSharedPtr& pHandler )
1084 { return pHandler->listenerAdded( xShape ); } );
1087 void EventMultiplexer::notifyShapeListenerRemoved(
1088 const uno::Reference<drawing::XShape>& xShape )
1090 mpImpl->maShapeListenerHandlers.applyAll(
1091 [&xShape]( const ShapeListenerEventHandlerSharedPtr& pHandler )
1092 { return pHandler->listenerRemoved( xShape ); } );
1095 void EventMultiplexer::notifyUserPaintColor( RGBColor const& rUserColor )
1097 mpImpl->maUserPaintEventHandlers.applyAll(
1098 [&rUserColor]( const UserPaintEventHandlerSharedPtr& pHandler )
1099 { return pHandler->colorChanged( rUserColor ); } );
1102 void EventMultiplexer::notifyUserPaintStrokeWidth( double rUserStrokeWidth )
1104 mpImpl->maUserPaintEventHandlers.applyAll(
1105 [&rUserStrokeWidth]( const UserPaintEventHandlerSharedPtr& pHandler )
1106 { return pHandler->widthChanged( rUserStrokeWidth ); } );
1109 void EventMultiplexer::notifyUserPaintDisabled()
1111 mpImpl->maUserPaintEventHandlers.applyAll(
1112 std::mem_fn(&UserPaintEventHandler::disable));
1115 void EventMultiplexer::notifySwitchPenMode(){
1116 mpImpl->maUserPaintEventHandlers.applyAll(
1117 std::mem_fn(&UserPaintEventHandler::switchPenMode));
1120 void EventMultiplexer::notifySwitchEraserMode(){
1121 mpImpl->maUserPaintEventHandlers.applyAll(
1122 std::mem_fn(&UserPaintEventHandler::switchEraserMode));
1125 //adding erasing all ink features with UserPaintOverlay
1126 void EventMultiplexer::notifyEraseAllInk( bool bEraseAllInk )
1128 mpImpl->maUserPaintEventHandlers.applyAll(
1129 [&bEraseAllInk]( const UserPaintEventHandlerSharedPtr& pHandler )
1130 { return pHandler->eraseAllInkChanged( bEraseAllInk ); } );
1133 //adding erasing features with UserPaintOverlay
1134 void EventMultiplexer::notifyEraseInkWidth( sal_Int32 rEraseInkSize )
1136 mpImpl->maUserPaintEventHandlers.applyAll(
1137 [&rEraseInkSize]( const UserPaintEventHandlerSharedPtr& pHandler )
1138 { return pHandler->eraseInkWidthChanged( rEraseInkSize ); } );
1141 bool EventMultiplexer::notifyNextEffect()
1143 return mpImpl->notifyNextEffect();
1146 void EventMultiplexer::notifySlideStartEvent()
1148 mpImpl->maSlideStartHandlers.applyAll(
1149 std::mem_fn(&EventHandler::handleEvent) );
1152 bool EventMultiplexer::notifySlideEndEvent()
1154 return mpImpl->maSlideEndHandlers.applyAll(
1155 std::mem_fn(&EventHandler::handleEvent) );
1158 bool EventMultiplexer::notifyAnimationStart(
1159 const AnimationNodeSharedPtr& rNode )
1161 return EventMultiplexerImpl::notifyAllAnimationHandlers( mpImpl->maAnimationStartHandlers,
1162 rNode );
1165 bool EventMultiplexer::notifyAnimationEnd(
1166 const AnimationNodeSharedPtr& rNode )
1168 return EventMultiplexerImpl::notifyAllAnimationHandlers( mpImpl->maAnimationEndHandlers,
1169 rNode );
1172 bool EventMultiplexer::notifySlideAnimationsEnd()
1174 return mpImpl->maSlideAnimationsEndHandlers.applyAll(
1175 std::mem_fn(&EventHandler::handleEvent));
1178 bool EventMultiplexer::notifyAudioStopped(
1179 const AnimationNodeSharedPtr& rNode )
1181 return EventMultiplexerImpl::notifyAllAnimationHandlers(
1182 mpImpl->maAudioStoppedHandlers,
1183 rNode );
1186 bool EventMultiplexer::notifyCommandStopAudio(
1187 const AnimationNodeSharedPtr& rNode )
1189 return EventMultiplexerImpl::notifyAllAnimationHandlers(
1190 mpImpl->maCommandStopAudioHandlers,
1191 rNode );
1194 void EventMultiplexer::notifyPauseMode( bool bPauseShow )
1196 mpImpl->maPauseHandlers.applyAll(
1197 [&bPauseShow]( const PauseEventHandlerSharedPtr& pHandler )
1198 { return pHandler->handlePause( bPauseShow ); } );
1201 void EventMultiplexer::notifyViewAdded( const UnoViewSharedPtr& rView )
1203 ENSURE_OR_THROW( rView, "EventMultiplexer::notifyViewAdded(): Invalid view");
1205 // register event listener
1206 uno::Reference<presentation::XSlideShowView> const rUnoView(
1207 rView->getUnoView() );
1209 if( mpImpl->isMouseListenerRegistered() )
1210 rUnoView->addMouseListener(
1211 mpImpl->mxListener );
1213 if( !mpImpl->maMouseMoveHandlers.isEmpty() )
1214 rUnoView->addMouseMotionListener(
1215 mpImpl->mxListener );
1217 mpImpl->maViewHandlers.applyAll(
1218 [&rView]( const ViewEventHandlerWeakPtr& pHandler )
1219 { return pHandler.lock()->viewAdded( rView ); } );
1222 void EventMultiplexer::notifyViewRemoved( const UnoViewSharedPtr& rView )
1224 ENSURE_OR_THROW( rView,
1225 "EventMultiplexer::removeView(): Invalid view" );
1227 // revoke event listeners
1228 uno::Reference<presentation::XSlideShowView> const rUnoView(
1229 rView->getUnoView() );
1231 if( mpImpl->isMouseListenerRegistered() )
1232 rUnoView->removeMouseListener(
1233 mpImpl->mxListener );
1235 if( !mpImpl->maMouseMoveHandlers.isEmpty() )
1236 rUnoView->removeMouseMotionListener(
1237 mpImpl->mxListener );
1239 mpImpl->maViewHandlers.applyAll(
1240 [&rView]( const ViewEventHandlerWeakPtr& pHandler )
1241 { return pHandler.lock()->viewRemoved( rView ); } );
1244 void EventMultiplexer::notifyViewChanged( const UnoViewSharedPtr& rView )
1246 mpImpl->maViewHandlers.applyAll(
1247 [&rView]( const ViewEventHandlerWeakPtr& pHandler )
1248 { return pHandler.lock()->viewChanged( rView ); } );
1251 void EventMultiplexer::notifyViewChanged( const uno::Reference<presentation::XSlideShowView>& xView )
1253 UnoViewSharedPtr pView( mpImpl->findUnoView(xView) );
1255 if( !pView )
1256 return; // view not registered here
1258 notifyViewChanged( pView );
1261 void EventMultiplexer::notifyViewsChanged()
1263 mpImpl->maViewHandlers.applyAll(
1264 std::mem_fn( &ViewEventHandler::viewsChanged ));
1267 void EventMultiplexer::notifyViewClobbered(
1268 const uno::Reference<presentation::XSlideShowView>& xView )
1270 UnoViewSharedPtr pView( mpImpl->findUnoView(xView) );
1272 if( !pView )
1273 return; // view not registered here
1275 mpImpl->maViewRepaintHandlers.applyAll(
1276 [&pView]( const ViewRepaintHandlerSharedPtr& pHandler )
1277 { return pHandler->viewClobbered( pView ); } );
1280 void EventMultiplexer::notifyHyperlinkClicked(
1281 OUString const& hyperLink )
1283 mpImpl->maHyperlinkHandlers.apply(
1284 [&hyperLink]( const PrioritizedHandlerEntry< HyperlinkHandler >& pHandler )
1285 { return pHandler.getHandler()->handleHyperlink( hyperLink ); } );
1288 basegfx::B2DPoint EventMultiplexer::toMatrixPoint(uno::Reference<uno::XInterface> xInterface,
1289 basegfx::B2DPoint pnt)
1291 uno::Reference<presentation::XSlideShowView> xView(xInterface, uno::UNO_QUERY_THROW);
1292 return mpImpl->toMatrixPoint(xView, pnt);
1295 basegfx::B2DPoint EventMultiplexer::toNormalPoint(uno::Reference<uno::XInterface> xInterface,
1296 basegfx::B2DPoint pnt)
1298 uno::Reference<presentation::XSlideShowView> xView(xInterface, uno::UNO_QUERY_THROW);
1299 return mpImpl->toNormalPoint(xView, pnt);
1302 } // namespace presentation
1304 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */