tdf#130857 qt weld: Support mail merge "Server Auth" dialog
[LibreOffice.git] / slideshow / source / engine / usereventqueue.cxx
blobcdca145151ba32f6667f80cb6608b6c4b4d173b0
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 <com/sun/star/awt/SystemPointer.hpp>
24 #include <com/sun/star/awt/MouseButton.hpp>
25 #include <com/sun/star/awt/MouseEvent.hpp>
27 #include <delayevent.hxx>
28 #include <usereventqueue.hxx>
29 #include <cursormanager.hxx>
31 #include <vector>
32 #include <queue>
33 #include <map>
34 #include <algorithm>
37 using namespace com::sun::star;
39 /* Implementation of UserEventQueue class */
41 namespace slideshow::internal {
43 namespace {
45 typedef std::vector<EventSharedPtr> ImpEventVector;
46 typedef std::queue<EventSharedPtr> ImpEventQueue;
47 typedef std::map<uno::Reference<animations::XAnimationNode>,
48 ImpEventVector> ImpAnimationEventMap;
49 typedef std::map<ShapeSharedPtr, ImpEventQueue,
50 Shape::lessThanShape> ImpShapeEventMap;
52 // MouseEventHandler base class, not consuming any event:
53 class MouseEventHandler_ : public MouseEventHandler
55 public:
56 virtual bool handleMousePressed( awt::MouseEvent const& /*e*/ ) override { return false;}
57 virtual bool handleMouseReleased( awt::MouseEvent const& /*e*/) override { return false;}
58 virtual bool handleMouseDragged( awt::MouseEvent const& /*e*/ ) override { return false;}
59 virtual bool handleMouseMoved( awt::MouseEvent const& /*e*/ ) override { return false; }
62 /** @return one event has been posted
64 template <typename ContainerT>
65 bool fireSingleEvent( ContainerT & rQueue, EventQueue & rEventQueue )
67 // post next event in given queue:
68 while (! rQueue.empty())
70 EventSharedPtr const pEvent(rQueue.front());
71 rQueue.pop();
73 // skip all inactive events (as the purpose of
74 // nextEventFromQueue() is to activate the next
75 // event, and events which return false on
76 // isCharged() will never be activated by the
77 // EventQueue)
78 if(pEvent->isCharged())
79 return rEventQueue.addEvent( pEvent );
81 return false; // no more (active) events in queue
84 /** @return at least one event has been posted
86 template <typename ContainerT>
87 bool fireAllEvents( ContainerT & rQueue, EventQueue & rEventQueue )
89 bool bFiredAny = false;
90 while (fireSingleEvent( rQueue, rEventQueue ))
91 bFiredAny = true;
92 return bFiredAny;
95 class EventContainer
97 public:
98 EventContainer() :
99 maEvents()
102 void addEvent( const EventSharedPtr& rEvent )
104 maEvents.push( rEvent );
107 protected:
108 ImpEventQueue maEvents;
111 } // anon namespace
113 class AllAnimationEventHandler : public AnimationEventHandler
115 public:
116 explicit AllAnimationEventHandler( EventQueue& rEventQueue ) :
117 mrEventQueue( rEventQueue ),
118 maAnimationEventMap()
121 virtual bool handleAnimationEvent( const AnimationNodeSharedPtr& rNode ) override
123 ENSURE_OR_RETURN_FALSE(
124 rNode,
125 "AllAnimationEventHandler::handleAnimationEvent(): Invalid node" );
127 bool bRet( false );
129 ImpAnimationEventMap::iterator aIter;
130 if( (aIter=maAnimationEventMap.find(
131 rNode->getXAnimationNode() )) != maAnimationEventMap.end() )
133 ImpEventVector& rVec( aIter->second );
135 bRet = !rVec.empty();
137 // registered node found -> fire all events in the vector
138 for( const auto& pEvent : rVec )
139 mrEventQueue.addEvent( pEvent );
141 rVec.clear();
144 return bRet;
147 void addEvent( const EventSharedPtr& rEvent,
148 const uno::Reference< animations::XAnimationNode >& xNode )
150 ImpAnimationEventMap::iterator aIter;
151 if( (aIter=maAnimationEventMap.find( xNode )) ==
152 maAnimationEventMap.end() )
154 // no entry for this animation -> create one
155 aIter = maAnimationEventMap.emplace( xNode, ImpEventVector() ).first;
158 // add new event to queue
159 aIter->second.push_back( rEvent );
162 private:
163 EventQueue& mrEventQueue;
164 ImpAnimationEventMap maAnimationEventMap;
167 class ClickEventHandler : public MouseEventHandler_,
168 public EventHandler,
169 public EventContainer
171 public:
172 explicit ClickEventHandler( EventQueue& rEventQueue ) :
173 EventContainer(),
174 mrEventQueue( rEventQueue ),
175 mbAdvanceOnClick( true )
178 void setAdvanceOnClick( bool bAdvanceOnClick )
180 mbAdvanceOnClick = bAdvanceOnClick;
183 private:
185 // triggered by API calls, e.g. space bar
186 virtual bool handleEvent() override
188 return handleEvent_impl();
191 // triggered by mouse release:
192 virtual bool handleMouseReleased( const awt::MouseEvent& evt ) override
194 if(evt.Buttons != awt::MouseButton::LEFT)
195 return false;
197 if( mbAdvanceOnClick ) {
198 // fire next event
199 return handleEvent_impl();
201 else {
202 return false; // advance-on-click disabled
206 // triggered by both:
207 virtual bool handleEvent_impl()
209 // fire next event:
210 return fireSingleEvent( maEvents, mrEventQueue );
213 private:
214 EventQueue& mrEventQueue;
215 bool mbAdvanceOnClick;
218 class SkipEffectEventHandler : public ClickEventHandler
220 public:
221 SkipEffectEventHandler( EventQueue & rEventQueue,
222 EventMultiplexer & rEventMultiplexer )
223 : ClickEventHandler(rEventQueue),
224 mrEventQueue(rEventQueue),
225 mrEventMultiplexer(rEventMultiplexer),
226 mbSkipTriggersNextEffect(true) {}
228 /** Remember to trigger (or not to trigger) the next effect after the
229 current effect is skipped.
231 void setSkipTriggersNextEffect (const bool bSkipTriggersNextEffect)
232 { mbSkipTriggersNextEffect = bSkipTriggersNextEffect; }
234 /// Skip the current effect but do not trigger the next effect.
235 void skipEffect() { handleEvent_impl(false); }
237 private:
238 virtual bool handleEvent_impl() override
240 return handleEvent_impl(true);
243 bool handleEvent_impl (bool bNotifyNextEffect)
245 // fire all events, so animation nodes can register their
246 // next effect listeners:
247 if(fireAllEvents( maEvents, mrEventQueue ))
249 if (mbSkipTriggersNextEffect && bNotifyNextEffect)
251 // then simulate a next effect event: this skip effect
252 // handler is triggered upon next effect events (multiplexer
253 // prio=-1)! Posting a notifyNextEffect() here is only safe
254 // (we don't run into busy loop), because we assume that
255 // someone has registered above for next effects
256 // (multiplexer prio=0) at the user event queue.
257 return mrEventQueue.addEventWhenQueueIsEmpty(
258 makeEvent( [this] () {
259 this->mrEventMultiplexer.notifyNextEffect();
260 }, u"EventMultiplexer::notifyNextEffect"_ustr) );
262 else
263 return true;
265 return false;
268 private:
269 EventQueue & mrEventQueue;
270 EventMultiplexer & mrEventMultiplexer;
271 bool mbSkipTriggersNextEffect;
274 namespace {
276 /** Base class to share some common code between
277 ShapeClickEventHandler and MouseMoveHandler
279 @derive override necessary MouseEventHandler interface methods,
280 call sendEvent() method to actually process the event.
282 class MouseHandlerBase : public MouseEventHandler_
284 public:
285 explicit MouseHandlerBase( EventQueue& rEventQueue ) :
286 mrEventQueue( rEventQueue ),
287 maShapeEventMap()
290 void addEvent( const EventSharedPtr& rEvent,
291 const ShapeSharedPtr& rShape )
293 ImpShapeEventMap::iterator aIter;
294 if( (aIter=maShapeEventMap.find( rShape )) == maShapeEventMap.end() )
296 // no entry for this shape -> create one
297 aIter = maShapeEventMap.emplace(rShape, ImpEventQueue()).first;
300 // add new event to queue
301 aIter->second.push( rEvent );
304 protected:
305 bool hitTest( const awt::MouseEvent& e,
306 ImpShapeEventMap::reverse_iterator& o_rHitShape )
308 // find hit shape in map
309 const basegfx::B2DPoint aPosition( e.X, e.Y );
311 // find matching shape (scan reversely, to coarsely match
312 // paint order)
313 auto aCurrShape = std::find_if(maShapeEventMap.rbegin(), maShapeEventMap.rend(),
314 [&aPosition](const ImpShapeEventMap::value_type& rShape) {
315 // TODO(F2): Get proper geometry polygon from the
316 // shape, to avoid having areas outside the shape
317 // react on the mouse
318 return rShape.first->getBounds().isInside( aPosition )
319 && rShape.first->isVisible();
321 if (aCurrShape != maShapeEventMap.rend())
323 // shape hit, and shape is visible - report a
324 // hit
325 o_rHitShape = aCurrShape;
326 return true;
329 return false; // nothing hit
332 bool sendEvent( ImpShapeEventMap::reverse_iterator const & io_rHitShape )
334 // take next event from queue
335 const bool bRet( fireSingleEvent( io_rHitShape->second,
336 mrEventQueue ) );
338 // clear shape entry, if its queue is
339 // empty. This is important, since the shapes
340 // are held by shared ptr, and might otherwise
341 // not get released, even after their owning
342 // slide is long gone.
343 if( io_rHitShape->second.empty() )
345 // this looks funny, since ::std::map does
346 // provide an erase( iterator )
347 // method. Unfortunately, C++ does not
348 // declare the obvious erase(
349 // reverse_iterator ) needed here (missing
350 // orthogonality, eh?)
351 maShapeEventMap.erase( io_rHitShape->first );
354 return bRet;
357 bool processEvent( const awt::MouseEvent& e )
359 ImpShapeEventMap::reverse_iterator aCurrShape;
361 if( hitTest( e, aCurrShape ) )
362 return sendEvent( aCurrShape );
364 return false; // did not handle the event
367 private:
368 EventQueue& mrEventQueue;
369 ImpShapeEventMap maShapeEventMap;
374 class ShapeClickEventHandler : public MouseHandlerBase
376 public:
377 ShapeClickEventHandler( CursorManager& rCursorManager,
378 EventQueue& rEventQueue ) :
379 MouseHandlerBase( rEventQueue ),
380 mrCursorManager( rCursorManager )
383 virtual bool handleMouseReleased( const awt::MouseEvent& e ) override
385 if(e.Buttons != awt::MouseButton::LEFT)
386 return false;
387 return processEvent( e );
390 virtual bool handleMouseMoved( const awt::MouseEvent& e ) override
392 // TODO(P2): Maybe buffer last shape touched
394 // if we have a shape click event, and the mouse
395 // hovers over this shape, change cursor to hand
396 ImpShapeEventMap::reverse_iterator aDummy;
397 if( hitTest( e, aDummy ) )
398 mrCursorManager.requestCursor( awt::SystemPointer::REFHAND );
400 return false; // we don't /eat/ this event. Lower prio
401 // handler should see it, too.
404 private:
405 CursorManager& mrCursorManager;
408 class MouseEnterHandler : public MouseHandlerBase
410 public:
411 explicit MouseEnterHandler( EventQueue& rEventQueue )
412 : MouseHandlerBase( rEventQueue ),
413 mpLastShape() {}
415 virtual bool handleMouseMoved( const awt::MouseEvent& e ) override
417 // TODO(P2): Maybe buffer last shape touched, and
418 // check against that _first_
420 ImpShapeEventMap::reverse_iterator aCurr;
421 if( hitTest( e, aCurr ) )
423 if( aCurr->first != mpLastShape )
425 // we actually hit a shape, and it's different
426 // from the previous one - thus we just
427 // entered it, raise event
428 sendEvent( aCurr );
429 mpLastShape = aCurr->first;
432 else
434 // don't hit no shape - thus, last shape is NULL
435 mpLastShape.reset();
438 return false; // we don't /eat/ this event. Lower prio
439 // handler should see it, too.
442 private:
443 ShapeSharedPtr mpLastShape;
446 class MouseLeaveHandler : public MouseHandlerBase
448 public:
449 explicit MouseLeaveHandler( EventQueue& rEventQueue )
450 : MouseHandlerBase( rEventQueue ),
451 maLastIter() {}
453 virtual bool handleMouseMoved( const awt::MouseEvent& e ) override
455 // TODO(P2): Maybe buffer last shape touched, and
456 // check against that _first_
458 ImpShapeEventMap::reverse_iterator aCurr;
459 if( hitTest( e, aCurr ) )
461 maLastIter = aCurr;
463 else
465 if( maLastIter->first )
467 // last time, we were over a shape, now we're
468 // not - we thus just left that shape, raise
469 // event
470 sendEvent( maLastIter );
473 // in any case, when we hit this else-branch: no
474 // shape hit, thus have to clear maLastIter
475 maLastIter = ImpShapeEventMap::reverse_iterator();
478 return false; // we don't /eat/ this event. Lower prio
479 // handler should see it, too.
482 private:
483 ImpShapeEventMap::reverse_iterator maLastIter;
486 template< typename Handler, typename Functor >
487 void UserEventQueue::registerEvent(
488 std::shared_ptr< Handler >& rHandler,
489 const EventSharedPtr& rEvent,
490 const Functor& rRegistrationFunctor )
492 ENSURE_OR_THROW( rEvent,
493 "UserEventQueue::registerEvent(): Invalid event" );
495 if( !rHandler ) {
496 // create handler
497 rHandler = std::make_shared<Handler>( mrEventQueue );
498 // register handler on EventMultiplexer
499 rRegistrationFunctor( rHandler );
502 rHandler->addEvent( rEvent );
505 template< typename Handler, typename Arg, typename Functor >
506 void UserEventQueue::registerEvent(
507 std::shared_ptr< Handler >& rHandler,
508 const EventSharedPtr& rEvent,
509 const Arg& rArg,
510 const Functor& rRegistrationFunctor )
512 ENSURE_OR_THROW( rEvent,
513 "UserEventQueue::registerEvent(): Invalid event" );
515 if( !rHandler ) {
516 // create handler
517 rHandler = std::make_shared<Handler>( mrEventQueue );
519 // register handler on EventMultiplexer
520 rRegistrationFunctor( rHandler );
523 rHandler->addEvent( rEvent, rArg );
527 UserEventQueue::UserEventQueue( EventMultiplexer& rMultiplexer,
528 EventQueue& rEventQueue,
529 CursorManager& rCursorManager )
530 : mrMultiplexer( rMultiplexer ),
531 mrEventQueue( rEventQueue ),
532 mrCursorManager( rCursorManager ),
533 mpAnimationStartEventHandler(),
534 mpAnimationEndEventHandler(),
535 mpAudioStoppedEventHandler(),
536 mpClickEventHandler(),
537 mpSkipEffectEventHandler(),
538 mpMouseEnterHandler(),
539 mpMouseLeaveHandler(),
540 mbAdvanceOnClick( true )
544 UserEventQueue::~UserEventQueue()
548 // unregister all handlers
549 clear();
551 catch (const uno::Exception&)
553 TOOLS_WARN_EXCEPTION("slideshow", "");
557 void UserEventQueue::clear()
559 // unregister and delete all handlers
560 if( mpAnimationStartEventHandler ) {
561 mrMultiplexer.removeAnimationStartHandler(
562 mpAnimationStartEventHandler );
563 mpAnimationStartEventHandler.reset();
565 if( mpAnimationEndEventHandler ) {
566 mrMultiplexer.removeAnimationEndHandler( mpAnimationEndEventHandler );
567 mpAnimationEndEventHandler.reset();
569 if( mpAudioStoppedEventHandler ) {
570 mrMultiplexer.removeAudioStoppedHandler( mpAudioStoppedEventHandler );
571 mpAudioStoppedEventHandler.reset();
573 if( mpShapeClickEventHandler ) {
574 mrMultiplexer.removeClickHandler( mpShapeClickEventHandler );
575 mrMultiplexer.removeMouseMoveHandler( mpShapeClickEventHandler );
576 mpShapeClickEventHandler.reset();
578 if( mpClickEventHandler ) {
579 mrMultiplexer.removeClickHandler( mpClickEventHandler );
580 mrMultiplexer.removeNextEffectHandler( mpClickEventHandler );
581 mpClickEventHandler.reset();
583 if(mpSkipEffectEventHandler) {
584 mrMultiplexer.removeClickHandler( mpSkipEffectEventHandler );
585 mrMultiplexer.removeNextEffectHandler( mpSkipEffectEventHandler );
586 mpSkipEffectEventHandler.reset();
588 if( mpShapeDoubleClickEventHandler ) {
589 mrMultiplexer.removeDoubleClickHandler( mpShapeDoubleClickEventHandler );
590 mrMultiplexer.removeMouseMoveHandler( mpShapeDoubleClickEventHandler );
591 mpShapeDoubleClickEventHandler.reset();
593 if( mpMouseEnterHandler ) {
594 mrMultiplexer.removeMouseMoveHandler( mpMouseEnterHandler );
595 mpMouseEnterHandler.reset();
597 if( mpMouseLeaveHandler ) {
598 mrMultiplexer.removeMouseMoveHandler( mpMouseLeaveHandler );
599 mpMouseLeaveHandler.reset();
603 void UserEventQueue::setAdvanceOnClick( bool bAdvanceOnClick )
605 mbAdvanceOnClick = bAdvanceOnClick;
607 // forward to handler, if existing. Otherwise, the handler
608 // creation will do the forwarding.
609 if( mpClickEventHandler )
610 mpClickEventHandler->setAdvanceOnClick( bAdvanceOnClick );
613 void UserEventQueue::registerAnimationStartEvent(
614 const EventSharedPtr& rEvent,
615 const uno::Reference< animations::XAnimationNode>& xNode )
617 registerEvent( mpAnimationStartEventHandler,
618 rEvent,
619 xNode,
620 [this]( const AnimationEventHandlerSharedPtr& rHandler )
621 { return this->mrMultiplexer.addAnimationStartHandler( rHandler ); } );
624 void UserEventQueue::registerAnimationEndEvent(
625 const EventSharedPtr& rEvent,
626 const uno::Reference<animations::XAnimationNode>& xNode )
628 registerEvent( mpAnimationEndEventHandler,
629 rEvent,
630 xNode,
631 [this]( const AnimationEventHandlerSharedPtr& rHandler )
632 { return this->mrMultiplexer.addAnimationEndHandler( rHandler ); } );
635 void UserEventQueue::registerAudioStoppedEvent(
636 const EventSharedPtr& rEvent,
637 const uno::Reference<animations::XAnimationNode>& xNode )
639 registerEvent( mpAudioStoppedEventHandler,
640 rEvent,
641 xNode,
642 [this]( const AnimationEventHandlerSharedPtr& rHandler )
643 { return this->mrMultiplexer.addAudioStoppedHandler( rHandler ); } );
646 void UserEventQueue::registerShapeClickEvent( const EventSharedPtr& rEvent,
647 const ShapeSharedPtr& rShape )
649 ENSURE_OR_THROW(
650 rEvent,
651 "UserEventQueue::registerShapeClickEvent(): Invalid event" );
653 if( !mpShapeClickEventHandler )
655 // create handler
656 mpShapeClickEventHandler =
657 std::make_shared<ShapeClickEventHandler>(mrCursorManager,
658 mrEventQueue);
660 // register handler on EventMultiplexer
661 mrMultiplexer.addClickHandler( mpShapeClickEventHandler, 1.0 );
662 mrMultiplexer.addMouseMoveHandler( mpShapeClickEventHandler, 1.0 );
665 mpShapeClickEventHandler->addEvent( rEvent, rShape );
668 namespace {
669 class ClickEventRegistrationFunctor
671 public:
672 ClickEventRegistrationFunctor( EventMultiplexer& rMultiplexer,
673 double nPrio,
674 bool bAdvanceOnClick )
675 : mrMultiplexer( rMultiplexer ),
676 mnPrio(nPrio),
677 mbAdvanceOnClick( bAdvanceOnClick ) {}
679 void operator()( const std::shared_ptr<ClickEventHandler>& rHandler )const
681 // register the handler on _two_ sources: we want the
682 // nextEffect events, e.g. space bar, to trigger clicks, as well!
683 mrMultiplexer.addClickHandler( rHandler, mnPrio );
684 mrMultiplexer.addNextEffectHandler( rHandler, mnPrio );
686 // forward advance-on-click state to newly
687 // generated handler (that's the only reason why
688 // we're called here)
689 rHandler->setAdvanceOnClick( mbAdvanceOnClick );
692 private:
693 EventMultiplexer& mrMultiplexer;
694 double const mnPrio;
695 bool const mbAdvanceOnClick;
697 } // anon namespace
699 void UserEventQueue::registerNextEffectEvent( const EventSharedPtr& rEvent )
701 // TODO: better name may be mpNextEffectEventHandler? then we have
702 // next effect (=> waiting to be started)
703 // skip effect (skipping the currently running one)
704 // rewind effect (rewinding back running one and waiting (again)
705 // to be started)
706 registerEvent( mpClickEventHandler,
707 rEvent,
708 ClickEventRegistrationFunctor( mrMultiplexer,
709 0.0 /* default prio */,
710 mbAdvanceOnClick ) );
713 void UserEventQueue::registerSkipEffectEvent(
714 EventSharedPtr const & pEvent,
715 const bool bSkipTriggersNextEffect)
717 if(!mpSkipEffectEventHandler)
719 mpSkipEffectEventHandler =
720 std::make_shared<SkipEffectEventHandler>( mrEventQueue, mrMultiplexer );
721 // register the handler on _two_ sources: we want the
722 // nextEffect events, e.g. space bar, to trigger clicks, as well!
723 mrMultiplexer.addClickHandler( mpSkipEffectEventHandler,
724 -1.0 /* prio below default */ );
725 mrMultiplexer.addNextEffectHandler( mpSkipEffectEventHandler,
726 -1.0 /* prio below default */ );
727 // forward advance-on-click state to newly
728 // generated handler (that's the only reason why
729 // we're called here)
730 mpSkipEffectEventHandler->setAdvanceOnClick( mbAdvanceOnClick );
732 mpSkipEffectEventHandler->setSkipTriggersNextEffect(bSkipTriggersNextEffect);
733 mpSkipEffectEventHandler->addEvent( pEvent );
736 void UserEventQueue::registerShapeDoubleClickEvent(
737 const EventSharedPtr& rEvent,
738 const ShapeSharedPtr& rShape )
740 ENSURE_OR_THROW(
741 rEvent,
742 "UserEventQueue::registerShapeDoubleClickEvent(): Invalid event" );
744 if( !mpShapeDoubleClickEventHandler )
746 // create handler
747 mpShapeDoubleClickEventHandler =
748 std::make_shared<ShapeClickEventHandler>(mrCursorManager,
749 mrEventQueue);
751 // register handler on EventMultiplexer
752 mrMultiplexer.addDoubleClickHandler( mpShapeDoubleClickEventHandler,
753 1.0 );
754 mrMultiplexer.addMouseMoveHandler( mpShapeDoubleClickEventHandler,
755 1.0 );
758 mpShapeDoubleClickEventHandler->addEvent( rEvent, rShape );
761 void UserEventQueue::registerMouseEnterEvent( const EventSharedPtr& rEvent,
762 const ShapeSharedPtr& rShape )
764 registerEvent( mpMouseEnterHandler,
765 rEvent,
766 rShape,
767 [this]( const MouseEventHandlerSharedPtr& rHandler )
768 { return this->mrMultiplexer.addMouseMoveHandler( rHandler, 0.0 ); } );
771 void UserEventQueue::registerMouseLeaveEvent( const EventSharedPtr& rEvent,
772 const ShapeSharedPtr& rShape )
774 registerEvent( mpMouseLeaveHandler,
775 rEvent,
776 rShape,
777 [this]( const MouseEventHandlerSharedPtr& rHandler )
778 { return this->mrMultiplexer.addMouseMoveHandler( rHandler, 0.0 ); } );
781 void UserEventQueue::callSkipEffectEventHandler()
783 ::std::shared_ptr<SkipEffectEventHandler> pHandler (
784 ::std::dynamic_pointer_cast<SkipEffectEventHandler>(mpSkipEffectEventHandler));
785 if (pHandler)
786 pHandler->skipEffect();
789 } // namespace presentation
791 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */