Quelle eventmultiplexer.cxx
Sprache: C
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project .
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License , v . 2 . 0 . If a copy of the MPL was not distributed with this
* file , You can obtain one at http : //mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice :
*
* Licensed to the Apache Software Foundation ( ASF ) under one or more
* contributor license agreements . See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership . The ASF licenses this file to you under the Apache
* License , Version 2 . 0 ( the " License " ) ; you may not use this file
* except in compliance with the License . You may obtain a copy of
* the License at http : //www.apache.org/licenses/LICENSE-2.0 .
*/
#include <comphelper/diagnose_ex.hxx>
#include <rtl/ref.hxx>
#include <comphelper/compbase.hxx>
#include <com/sun/star/awt/XMouseListener.hpp>
#include <com/sun/star/awt/XMouseMotionListener.hpp>
#include <com/sun/star/presentation/XSlideShowView.hpp>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/numeric/ftools.hxx>
#include <basegfx/point/b2dpoint.hxx>
#include <eventqueue.hxx>
#include <eventmultiplexer.hxx>
#include <listenercontainer.hxx>
#include <delayevent.hxx>
#include <unoview.hxx>
#include <unoviewcontainer.hxx>
#include <functional>
#include <memory>
#include <algorithm>
#include <type_traits>
#include <utility>
#include <vector>
using namespace ::com::sun::star;
namespace
{
// add operator== for weak_ptr, so we can use std::find over lists of them
struct ViewEventHandlerWeakPtrWrapper final {
slideshow::internal::ViewEventHandlerWeakPtr ptr;
ViewEventHandlerWeakPtrWrapper(slideshow::internal::ViewEventHandlerWeakPtr thePtr):
ptr(std::move(thePtr)) {}
bool operator ==(ViewEventHandlerWeakPtrWrapper const & other) const
{ return ptr.lock().get() == other.ptr.lock().get(); }
};
}
// Needed by ImplViewHandlers; see the ListenerOperations<std::weak_ptr<ListenerTargetT>> partial
// specialization in slideshow/source/inc/listenercontainer.hxx:
template <>
struct slideshow::internal::ListenerOperations<ViewEventHandlerWeakPtrWrapper>
{
template < typename ContainerT,
typename FuncT >
static bool notifySingleListener( ContainerT& rContainer,
FuncT func )
{
for ( const auto & rCurr : rContainer )
{
std::shared_ptr<ViewEventHandler> pListener( rCurr.ptr.lock() );
if ( pListener && func(pListener) )
return true ;
}
return false ;
}
template < typename ContainerT,
typename FuncT >
static bool notifyAllListeners( ContainerT& rContainer,
FuncT func )
{
bool bRet(false );
for ( const auto & rCurr : rContainer )
{
std::shared_ptr<ViewEventHandler> pListener( rCurr.ptr.lock() );
if ( pListener.get() &&
FunctionApply<typename ::std::invoke_result<FuncT, std::shared_ptr<ViewEventHandler> const &>::type,
std::shared_ptr<ViewEventHandler> >::apply(func,pListener) )
{
bRet = true ;
}
}
return bRet;
}
template < typename ContainerT >
static void pruneListeners( ContainerT& rContainer,
size_t nSizeThreshold )
{
if ( rContainer.size() <= nSizeThreshold )
return ;
ContainerT aAliveListeners;
aAliveListeners.reserve(rContainer.size());
for ( const auto & rCurr : rContainer )
{
if ( !rCurr.ptr.expired() )
aAliveListeners.push_back( rCurr );
}
std::swap( rContainer, aAliveListeners );
}
};
namespace slideshow::internal {
namespace {
template <typename HandlerT>
class PrioritizedHandlerEntry
{
typedef std::shared_ptr<HandlerT> HandlerSharedPtrT;
HandlerSharedPtrT mpHandler;
double mnPrio;
public :
PrioritizedHandlerEntry( HandlerSharedPtrT pHandler,
double nPrio ) :
mpHandler(std::move(pHandler)),
mnPrio(nPrio)
{}
HandlerSharedPtrT const & getHandler() const { return mpHandler; }
/// To sort according to priority
bool operator <( PrioritizedHandlerEntry const & rRHS ) const
{
// reversed order - high prioritized entries
// should be at the beginning of the queue
return mnPrio > rRHS.mnPrio;
}
/// To permit std::remove in removeHandler template
bool operator ==( PrioritizedHandlerEntry const & rRHS ) const
{
// ignore prio, for removal, only the handler ptr matters
return mpHandler == rRHS.mpHandler;
}
};
}
typedef comphelper::WeakComponentImplHelper<
awt::XMouseListener,
awt::XMouseMotionListener > Listener_UnoBase;
namespace {
/** Listener class, to decouple UNO lifetime from EventMultiplexer
This class gets registered as the XMouse ( Motion ) Listener on the
XSlideViews , and passes on the events to the EventMultiplexer ( via
EventQueue indirection , to force the events into the main thread )
*/
class EventMultiplexerListener : public Listener_UnoBase
{
public :
EventMultiplexerListener( EventQueue& rEventQueue,
EventMultiplexerImpl& rEventMultiplexer ) :
mpEventQueue( &rEventQueue ),
mpEventMultiplexer( &rEventMultiplexer )
{
}
EventMultiplexerListener( const EventMultiplexerListener& ) = delete ;
EventMultiplexerListener& operator =( const EventMultiplexerListener& ) = delete ;
// WeakComponentImplHelperBase::disposing
virtual void disposing(std::unique_lock<std::mutex>& rGuard) override;
private :
virtual void SAL_CALL disposing( const lang::EventObject& Source ) override;
// XMouseListener implementation
virtual void SAL_CALL mousePressed( const awt::MouseEvent& e ) override;
virtual void SAL_CALL mouseReleased( const awt::MouseEvent& e ) override;
virtual void SAL_CALL mouseEntered( const awt::MouseEvent& e ) override;
virtual void SAL_CALL mouseExited( const awt::MouseEvent& e ) override;
// XMouseMotionListener implementation
virtual void SAL_CALL mouseDragged( const awt::MouseEvent& e ) override;
virtual void SAL_CALL mouseMoved( const awt::MouseEvent& e ) override;
EventQueue* mpEventQueue;
EventMultiplexerImpl* mpEventMultiplexer;
};
}
struct EventMultiplexerImpl
{
EventMultiplexerImpl( EventQueue& rEventQueue,
UnoViewContainer const & rViewContainer ) :
mrEventQueue(rEventQueue),
mrViewContainer(rViewContainer),
mxListener( new EventMultiplexerListener(rEventQueue,
*this ) ),
maNextEffectHandlers(),
maSlideStartHandlers(),
maSlideEndHandlers(),
maAnimationStartHandlers(),
maAnimationEndHandlers(),
maSlideAnimationsEndHandlers(),
maAudioStoppedHandlers(),
maCommandStopAudioHandlers(),
maPauseHandlers(),
maViewHandlers(),
maViewRepaintHandlers(),
maShapeListenerHandlers(),
maUserPaintEventHandlers(),
maMouseClickHandlers(),
maMouseDoubleClickHandlers(),
maMouseMoveHandlers(),
maHyperlinkHandlers(),
mnTimeout(0 .0 ),
mpTickEvent(),
mbIsAutoMode(false )
{}
~EventMultiplexerImpl()
{
if ( mxListener.is() )
mxListener->dispose();
}
/// Remove all handlers
void clear();
// actual handler callbacks (get called from the UNO interface
// listeners via event queue)
void mousePressed( const awt::MouseEvent& e );
void mouseReleased( const awt::MouseEvent& e );
void mouseDragged( const awt::MouseEvent& e );
void mouseMoved( const awt::MouseEvent& e );
bool isMouseListenerRegistered() const ;
typedef ThreadUnsafeListenerContainer<
PrioritizedHandlerEntry<EventHandler>,
std::vector<
PrioritizedHandlerEntry<EventHandler> > > ImplNextEffectHandlers;
typedef PrioritizedHandlerEntry<MouseEventHandler> ImplMouseHandlerEntry;
typedef ThreadUnsafeListenerContainer<
ImplMouseHandlerEntry,
std::vector<ImplMouseHandlerEntry> > ImplMouseHandlers;
typedef ThreadUnsafeListenerContainer<
EventHandlerSharedPtr,
std::vector<EventHandlerSharedPtr> > ImplEventHandlers;
typedef ThreadUnsafeListenerContainer<
AnimationEventHandlerSharedPtr,
std::vector<AnimationEventHandlerSharedPtr> > ImplAnimationHandlers;
typedef ThreadUnsafeListenerContainer<
PauseEventHandlerSharedPtr,
std::vector<PauseEventHandlerSharedPtr> > ImplPauseHandlers;
typedef ThreadUnsafeListenerContainer<
ViewEventHandlerWeakPtrWrapper,
std::vector<ViewEventHandlerWeakPtrWrapper> > ImplViewHandlers;
typedef ThreadUnsafeListenerContainer<
ViewRepaintHandlerSharedPtr,
std::vector<ViewRepaintHandlerSharedPtr> > ImplRepaintHandlers;
typedef ThreadUnsafeListenerContainer<
ShapeListenerEventHandlerSharedPtr,
std::vector<ShapeListenerEventHandlerSharedPtr> > ImplShapeListenerHandlers;
typedef ThreadUnsafeListenerContainer<
UserPaintEventHandlerSharedPtr,
std::vector<UserPaintEventHandlerSharedPtr> > ImplUserPaintEventHandlers;
typedef ThreadUnsafeListenerContainer<
PrioritizedHandlerEntry<HyperlinkHandler>,
std::vector<PrioritizedHandlerEntry<HyperlinkHandler> > > ImplHyperLinkHandlers;
template <typename XSlideShowViewFunc>
void forEachView( XSlideShowViewFunc pViewMethod );
UnoViewSharedPtr findUnoView(const uno::Reference<
presentation::XSlideShowView>& xView) const ;
template < typename RegisterFunction >
void addMouseHandler( ImplMouseHandlers& rHandlerContainer,
const MouseEventHandlerSharedPtr& rHandler,
double nPriority,
RegisterFunction pRegisterListener );
static bool notifyAllAnimationHandlers( ImplAnimationHandlers const & rContainer,
AnimationNodeSharedPtr const & rNode );
bool notifyMouseHandlers(
const ImplMouseHandlers& rQueue,
bool (MouseEventHandler::*pHandlerMethod)(
const awt::MouseEvent& ),
const awt::MouseEvent& e );
bool notifyNextEffect();
/// Called for automatic nextEffect
void tick();
/// Schedules a tick event
void scheduleTick();
/// Schedules tick events, if mbIsAutoMode is true
void handleTicks();
basegfx::B2DPoint toMatrixPoint(const uno::Reference<presentation::XSlideShowView>& xView,
const basegfx::B2DPoint& pnt);
basegfx::B2DPoint toNormalPoint(const uno::Reference<presentation::XSlideShowView>& xView,
const basegfx::B2DPoint& pnt);
EventQueue& mrEventQueue;
UnoViewContainer const & mrViewContainer;
::rtl::Reference<
EventMultiplexerListener> mxListener;
ImplNextEffectHandlers maNextEffectHandlers;
ImplEventHandlers maSlideStartHandlers;
ImplEventHandlers maSlideEndHandlers;
ImplAnimationHandlers maAnimationStartHandlers;
ImplAnimationHandlers maAnimationEndHandlers;
ImplEventHandlers maSlideAnimationsEndHandlers;
ImplAnimationHandlers maAudioStoppedHandlers;
ImplAnimationHandlers maCommandStopAudioHandlers;
ImplPauseHandlers maPauseHandlers;
ImplViewHandlers maViewHandlers;
ImplRepaintHandlers maViewRepaintHandlers;
ImplShapeListenerHandlers maShapeListenerHandlers;
ImplUserPaintEventHandlers maUserPaintEventHandlers;
ImplMouseHandlers maMouseClickHandlers;
ImplMouseHandlers maMouseDoubleClickHandlers;
ImplMouseHandlers maMouseMoveHandlers;
ImplHyperLinkHandlers maHyperlinkHandlers;
/// automatic next effect mode timeout
double mnTimeout;
/** Holds ptr to optional tick event weakly
When event queue is cleansed , the next
setAutomaticMode ( true ) call is then able to
regenerate the event .
*/
::std::weak_ptr< Event > mpTickEvent;
bool mbIsAutoMode;
};
void EventMultiplexerListener::disposing(std::unique_lock<std::mutex>& /*rGuard*/)
{
mpEventQueue = nullptr;
mpEventMultiplexer = nullptr;
}
void SAL_CALL EventMultiplexerListener::disposing(
const lang::EventObject& /*rSource*/ )
{
// there's no real point in acting on this message - after all,
// the event sources are the XSlideShowViews, which must be
// explicitly removed from the slideshow via
// XSlideShow::removeView(). thus, if a XSlideShowView has
// properly removed itself from the slideshow, it will not be
// found here. and if it hasn't, there'll be other references at
// other places within the slideshow, anyway...
}
void SAL_CALL EventMultiplexerListener::mousePressed(
const awt::MouseEvent& e )
{
std::unique_lock const guard( m_aMutex );
// notify mouse press. Don't call handlers directly, this
// might not be the main thread!
if ( mpEventQueue )
mpEventQueue->addEvent(
makeEvent( std::bind( &EventMultiplexerImpl::mousePressed,
mpEventMultiplexer,
e ),
u"EventMultiplexerImpl::mousePressed" _ustr) );
}
void SAL_CALL EventMultiplexerListener::mouseReleased(
const awt::MouseEvent& e )
{
std::unique_lock const guard( m_aMutex );
// notify mouse release. Don't call handlers directly,
// this might not be the main thread!
if ( mpEventQueue )
mpEventQueue->addEvent(
makeEvent( std::bind( &EventMultiplexerImpl::mouseReleased,
mpEventMultiplexer,
e ),
u"EventMultiplexerImpl::mouseReleased" _ustr) );
}
void SAL_CALL EventMultiplexerListener::mouseEntered(
const awt::MouseEvent& /*e*/ )
{
// not used here
}
void SAL_CALL EventMultiplexerListener::mouseExited(
const awt::MouseEvent& /*e*/ )
{
// not used here
}
// XMouseMotionListener implementation
void SAL_CALL EventMultiplexerListener::mouseDragged(
const awt::MouseEvent& e )
{
std::unique_lock const guard( m_aMutex );
// notify mouse drag. Don't call handlers directly, this
// might not be the main thread!
if ( mpEventQueue )
mpEventQueue->addEvent(
makeEvent( std::bind( &EventMultiplexerImpl::mouseDragged,
mpEventMultiplexer,
e ),
u"EventMultiplexerImpl::mouseDragged" _ustr) );
}
void SAL_CALL EventMultiplexerListener::mouseMoved(
const awt::MouseEvent& e )
{
std::unique_lock const guard( m_aMutex );
// notify mouse move. Don't call handlers directly, this
// might not be the main thread!
if ( mpEventQueue )
mpEventQueue->addEvent(
makeEvent( std::bind( &EventMultiplexerImpl::mouseMoved,
mpEventMultiplexer,
e ),
u"EventMultiplexerImpl::mouseMoved" _ustr) );
}
bool EventMultiplexerImpl::notifyAllAnimationHandlers( ImplAnimationHandlers const & rContainer,
AnimationNodeSharedPtr const & rNode )
{
return rContainer.applyAll(
[&rNode]( const AnimationEventHandlerSharedPtr& pEventHandler )
{ return pEventHandler->handleAnimationEvent( rNode ); } );
}
template <typename XSlideShowViewFunc>
void EventMultiplexerImpl::forEachView( XSlideShowViewFunc pViewMethod )
{
if ( !pViewMethod )
return ;
// (un)register mouse listener on all views
for ( UnoViewVector::const_iterator aIter( mrViewContainer.begin() ),
aEnd( mrViewContainer.end() ); aIter != aEnd; ++aIter )
{
uno::Reference<presentation::XSlideShowView> xView ((*aIter)->getUnoView());
if (xView.is())
{
(xView.get()->*pViewMethod)( mxListener.get() );
}
else
{
OSL_ASSERT(xView.is());
}
}
}
UnoViewSharedPtr EventMultiplexerImpl::findUnoView(
const uno::Reference<presentation::XSlideShowView>& xView) const
{
// find view from which the change originated
UnoViewVector::const_iterator aIter;
const UnoViewVector::const_iterator aEnd ( mrViewContainer.end() );
if ( (aIter=std::find_if( mrViewContainer.begin(),
aEnd,
[&xView]( const UnoViewSharedPtr& pView )
{ return xView == pView->getUnoView(); } )) == aEnd )
{
OSL_FAIL("EventMultiplexer::findUnoView(): unexpected message source" );
return UnoViewSharedPtr();
}
return *aIter;
}
template < typename RegisterFunction >
void EventMultiplexerImpl::addMouseHandler(
ImplMouseHandlers& rHandlerContainer,
const MouseEventHandlerSharedPtr& rHandler,
double nPriority,
RegisterFunction pRegisterListener )
{
ENSURE_OR_THROW(
rHandler,
"EventMultiplexer::addMouseHandler(): Invalid handler" );
// register mouse listener on all views
forEachView( pRegisterListener );
// add into sorted container:
rHandlerContainer.addSorted(
typename ImplMouseHandlers::container_type::value_type(
rHandler,
nPriority ));
}
bool EventMultiplexerImpl::isMouseListenerRegistered() const
{
return !(maMouseClickHandlers.isEmpty() &&
maMouseDoubleClickHandlers.isEmpty());
}
void EventMultiplexerImpl::tick()
{
if ( !mbIsAutoMode )
return ; // this event is just a left-over, ignore
notifyNextEffect();
if ( !maNextEffectHandlers.isEmpty() )
{
// still handlers left, schedule next timeout
// event. Will also set mbIsTickEventOn back to true
scheduleTick();
}
}
void EventMultiplexerImpl::scheduleTick()
{
EventSharedPtr pEvent(
makeDelay( [this ] () { this ->tick(); },
mnTimeout,
u"EventMultiplexerImpl::tick with delay" _ustr));
// store weak reference to generated event, to notice when
// the event queue gets cleansed (we then have to
// regenerate the tick event!)
mpTickEvent = pEvent;
// enabled auto mode: simply schedule a timeout event,
// which will eventually call our tick() method
mrEventQueue.addEventForNextRound( pEvent );
}
void EventMultiplexerImpl::handleTicks()
{
if ( !mbIsAutoMode )
return ; // nothing to do, don't need no ticks
EventSharedPtr pTickEvent( mpTickEvent.lock() );
if ( pTickEvent )
return ; // nothing to do, there's already a tick
// pending
// schedule initial tick (which reschedules itself
// after that, all by itself)
scheduleTick();
}
basegfx::B2DPoint
EventMultiplexerImpl::toNormalPoint(const uno::Reference<presentation::XSlideShowView>& xView,
const basegfx::B2DPoint& pnt)
{
UnoViewVector::const_iterator aIter;
const UnoViewVector::const_iterator aEnd(mrViewContainer.end());
if ((aIter = std::find_if(
mrViewContainer.begin(), aEnd,
[&xView](const UnoViewSharedPtr& pView) { return xView == pView->getUnoView(); }))
== aEnd)
{
return pnt;
}
basegfx::B2DPoint aPosition(pnt.getX(), pnt.getY());
basegfx::B2DHomMatrix aMatrix((*aIter)->getTransformation());
aPosition *= aMatrix;
aPosition.setX(std::round(aPosition.getX()));
aPosition.setY(std::round(aPosition.getY()));
return aPosition;
}
basegfx::B2DPoint
EventMultiplexerImpl::toMatrixPoint(const uno::Reference<presentation::XSlideShowView>& xView,
const basegfx::B2DPoint& pnt)
{
UnoViewVector::const_iterator aIter;
const UnoViewVector::const_iterator aEnd(mrViewContainer.end());
if ((aIter = std::find_if(
mrViewContainer.begin(), aEnd,
[&xView](const UnoViewSharedPtr& pView) { return xView == pView->getUnoView(); }))
== aEnd)
{
return pnt;
}
basegfx::B2DPoint aPosition(pnt.getX(), pnt.getY());
basegfx::B2DHomMatrix aMatrix((*aIter)->getTransformation());
if (!aMatrix.invert())
ENSURE_OR_THROW(false , "EventMultiplexer::notifyHandlers():"
" view matrix singular" );
aPosition *= aMatrix;
aPosition.setX(std::round(aPosition.getX()));
aPosition.setY(std::round(aPosition.getY()));
return aPosition;
}
void EventMultiplexerImpl::clear()
{
// deregister from all views.
if ( isMouseListenerRegistered() )
{
for ( UnoViewVector::const_iterator aIter=mrViewContainer.begin(),
aEnd=mrViewContainer.end();
aIter!=aEnd;
++aIter )
{
if ( (*aIter)->getUnoView().is() )
(*aIter)->getUnoView()->removeMouseListener( mxListener );
}
}
if ( !maMouseMoveHandlers.isEmpty() )
{
for ( UnoViewVector::const_iterator aIter=mrViewContainer.begin(),
aEnd=mrViewContainer.end();
aIter!=aEnd;
++aIter )
{
if ( (*aIter)->getUnoView().is() )
(*aIter)->getUnoView()->removeMouseMotionListener( mxListener );
}
}
// clear all handlers (releases all references)
maNextEffectHandlers.clear();
maSlideStartHandlers.clear();
maSlideEndHandlers.clear();
maAnimationStartHandlers.clear();
maAnimationEndHandlers.clear();
maSlideAnimationsEndHandlers.clear();
maAudioStoppedHandlers.clear();
maCommandStopAudioHandlers.clear();
maPauseHandlers.clear();
maViewHandlers.clear();
maViewRepaintHandlers.clear();
maMouseClickHandlers.clear();
maMouseDoubleClickHandlers.clear();
maMouseMoveHandlers.clear();
maHyperlinkHandlers.clear();
mpTickEvent.reset();
}
// XMouseListener implementation
bool EventMultiplexerImpl::notifyMouseHandlers(
const ImplMouseHandlers& rQueue,
bool (MouseEventHandler::*pHandlerMethod)( const awt::MouseEvent& ),
const awt::MouseEvent& e )
{
uno::Reference<presentation::XSlideShowView> xView(
e.Source, uno::UNO_QUERY );
ENSURE_OR_RETURN_FALSE( xView.is(), "EventMultiplexer::notifyHandlers(): "
"event source is not an XSlideShowView" );
// find corresponding view (to map mouse position into user
// coordinate space)
UnoViewVector::const_iterator aIter;
const UnoViewVector::const_iterator aEnd ( mrViewContainer.end() );
if ( (aIter=::std::find_if(
mrViewContainer.begin(),
aEnd,
[&xView]( const UnoViewSharedPtr& pView )
{ return xView == pView->getUnoView(); } )) == aEnd )
{
ENSURE_OR_RETURN_FALSE(
false , "EventMultiplexer::notifyHandlers(): "
"event source not found under registered views" );
}
// convert mouse position to user coordinate space
::basegfx::B2DPoint aPosition( e.X, e.Y );
::basegfx::B2DHomMatrix aMatrix( (*aIter)->getTransformation() );
if ( !aMatrix.invert() )
ENSURE_OR_THROW( false , "EventMultiplexer::notifyHandlers():"
" view matrix singular" );
aPosition *= aMatrix;
awt::MouseEvent aEvent( e );
aEvent.X = ::basegfx::fround( aPosition.getX() );
aEvent.Y = ::basegfx::fround( aPosition.getY() );
// fire event on handlers, try in order of precedence. If
// one high-priority handler rejects the event
// (i.e. returns false), try next handler.
return rQueue.apply(
[&pHandlerMethod, &aEvent]( const ImplMouseHandlerEntry& rMouseHandler )
{ return ( ( *rMouseHandler.getHandler() ).*pHandlerMethod )( aEvent ); } );
}
void EventMultiplexerImpl::mousePressed( const awt::MouseEvent& e )
{
// fire double-click events for every second click
sal_Int32 nCurrClickCount = e.ClickCount;
while ( nCurrClickCount > 1 &&
notifyMouseHandlers( maMouseDoubleClickHandlers,
&MouseEventHandler::handleMousePressed,
e ))
{
nCurrClickCount -= 2 ;
}
// fire single-click events for all remaining clicks
while ( nCurrClickCount > 0 &&
notifyMouseHandlers( maMouseClickHandlers,
&MouseEventHandler::handleMousePressed,
e ))
{
--nCurrClickCount;
}
}
void EventMultiplexerImpl::mouseReleased( const awt::MouseEvent& e )
{
// fire double-click events for every second click
sal_Int32 nCurrClickCount = e.ClickCount;
while ( nCurrClickCount > 1 &&
notifyMouseHandlers( maMouseDoubleClickHandlers,
&MouseEventHandler::handleMouseReleased,
e ))
{
nCurrClickCount -= 2 ;
}
// fire single-click events for all remaining clicks
while ( nCurrClickCount > 0 &&
notifyMouseHandlers( maMouseClickHandlers,
&MouseEventHandler::handleMouseReleased,
e ))
{
--nCurrClickCount;
}
}
void EventMultiplexerImpl::mouseDragged( const awt::MouseEvent& e )
{
notifyMouseHandlers( maMouseMoveHandlers,
&MouseEventHandler::handleMouseDragged,
e );
}
void EventMultiplexerImpl::mouseMoved( const awt::MouseEvent& e )
{
notifyMouseHandlers( maMouseMoveHandlers,
&MouseEventHandler::handleMouseMoved,
e );
}
bool EventMultiplexerImpl::notifyNextEffect()
{
// fire event on handlers, try in order of precedence. If one
// high-priority handler rejects the event (i.e. returns false),
// try next handler.
return maNextEffectHandlers.apply(
[]( const PrioritizedHandlerEntry< EventHandler >& pHandler )
{ return pHandler.getHandler()->handleEvent(); } );
}
EventMultiplexer::EventMultiplexer( EventQueue& rEventQueue,
UnoViewContainer const & rViewContainer ) :
mpImpl( new EventMultiplexerImpl(rEventQueue, rViewContainer) )
{
}
EventMultiplexer::~EventMultiplexer()
{
// outline because of EventMultiplexerImpl's incomplete type
}
void EventMultiplexer::clear()
{
mpImpl->clear();
}
void EventMultiplexer::setAutomaticMode( bool bIsAuto )
{
if ( bIsAuto == mpImpl->mbIsAutoMode )
return ; // no change, nothing to do
mpImpl->mbIsAutoMode = bIsAuto;
mpImpl->handleTicks();
}
bool EventMultiplexer::getAutomaticMode() const
{
return mpImpl->mbIsAutoMode;
}
void EventMultiplexer::setAutomaticTimeout( double nTimeout )
{
mpImpl->mnTimeout = nTimeout;
}
double EventMultiplexer::getAutomaticTimeout() const
{
return mpImpl->mnTimeout;
}
void EventMultiplexer::addNextEffectHandler(
EventHandlerSharedPtr const & rHandler,
double nPriority )
{
mpImpl->maNextEffectHandlers.addSorted(
EventMultiplexerImpl::ImplNextEffectHandlers::container_type::value_type(
rHandler,
nPriority) );
// Enable tick events, if not done already
mpImpl->handleTicks();
}
void EventMultiplexer::removeNextEffectHandler(
const EventHandlerSharedPtr& rHandler )
{
mpImpl->maNextEffectHandlers.remove(
EventMultiplexerImpl::ImplNextEffectHandlers::container_type::value_type(
rHandler,
0 .0 ) );
}
void EventMultiplexer::addSlideStartHandler(
const EventHandlerSharedPtr& rHandler )
{
mpImpl->maSlideStartHandlers.add( rHandler );
}
void EventMultiplexer::removeSlideStartHandler(
const EventHandlerSharedPtr& rHandler )
{
mpImpl->maSlideStartHandlers.remove( rHandler );
}
void EventMultiplexer::addSlideEndHandler(
const EventHandlerSharedPtr& rHandler )
{
mpImpl->maSlideEndHandlers.add( rHandler );
}
void EventMultiplexer::removeSlideEndHandler(
const EventHandlerSharedPtr& rHandler )
{
mpImpl->maSlideEndHandlers.remove( rHandler );
}
void EventMultiplexer::addAnimationStartHandler(
const AnimationEventHandlerSharedPtr& rHandler )
{
mpImpl->maAnimationStartHandlers.add( rHandler );
}
void EventMultiplexer::removeAnimationStartHandler(
const AnimationEventHandlerSharedPtr& rHandler )
{
mpImpl->maAnimationStartHandlers.remove( rHandler );
}
void EventMultiplexer::addAnimationEndHandler(
const AnimationEventHandlerSharedPtr& rHandler )
{
mpImpl->maAnimationEndHandlers.add( rHandler );
}
void EventMultiplexer::removeAnimationEndHandler(
const AnimationEventHandlerSharedPtr& rHandler )
{
mpImpl->maAnimationEndHandlers.remove( rHandler );
}
void EventMultiplexer::addSlideAnimationsEndHandler(
const EventHandlerSharedPtr& rHandler )
{
mpImpl->maSlideAnimationsEndHandlers.add( rHandler );
}
void EventMultiplexer::removeSlideAnimationsEndHandler(
const EventHandlerSharedPtr& rHandler )
{
mpImpl->maSlideAnimationsEndHandlers.remove( rHandler );
}
void EventMultiplexer::addAudioStoppedHandler(
const AnimationEventHandlerSharedPtr& rHandler )
{
mpImpl->maAudioStoppedHandlers.add( rHandler );
}
void EventMultiplexer::removeAudioStoppedHandler(
const AnimationEventHandlerSharedPtr& rHandler )
{
mpImpl->maAudioStoppedHandlers.remove( rHandler );
}
void EventMultiplexer::addCommandStopAudioHandler(
const AnimationEventHandlerSharedPtr& rHandler )
{
mpImpl->maCommandStopAudioHandlers.add( rHandler );
}
void EventMultiplexer::removeCommandStopAudioHandler(
const AnimationEventHandlerSharedPtr& rHandler )
{
mpImpl->maCommandStopAudioHandlers.remove( rHandler );
}
void EventMultiplexer::addPauseHandler(
const PauseEventHandlerSharedPtr& rHandler )
{
mpImpl->maPauseHandlers.add( rHandler );
}
void EventMultiplexer::removePauseHandler(
const PauseEventHandlerSharedPtr& rHandler )
{
mpImpl->maPauseHandlers.remove( rHandler );
}
void EventMultiplexer::addViewHandler(
const ViewEventHandlerWeakPtr& rHandler )
{
mpImpl->maViewHandlers.add( rHandler );
}
void EventMultiplexer::removeViewHandler( const ViewEventHandlerWeakPtr& rHandler )
{
mpImpl->maViewHandlers.remove( rHandler );
}
void EventMultiplexer::addViewRepaintHandler( const ViewRepaintHandlerSharedPtr& rHandler )
{
mpImpl->maViewRepaintHandlers.add( rHandler );
}
void EventMultiplexer::removeViewRepaintHandler( const ViewRepaintHandlerSharedPtr& rHandler )
{
mpImpl->maViewRepaintHandlers.remove( rHandler );
}
void EventMultiplexer::addShapeListenerHandler( const ShapeListenerEventHandlerSharedPtr& rHandler )
{
mpImpl->maShapeListenerHandlers.add( rHandler );
}
void EventMultiplexer::removeShapeListenerHandler( const ShapeListenerEventHandlerSharedPtr& rHandler )
{
mpImpl->maShapeListenerHandlers.remove( rHandler );
}
void EventMultiplexer::addUserPaintHandler( const UserPaintEventHandlerSharedPtr& rHandler )
{
mpImpl->maUserPaintEventHandlers.add( rHandler );
}
void EventMultiplexer::addClickHandler(
const MouseEventHandlerSharedPtr& rHandler,
double nPriority )
{
mpImpl->addMouseHandler(
mpImpl->maMouseClickHandlers,
rHandler,
nPriority,
mpImpl->isMouseListenerRegistered()
? nullptr
: &presentation::XSlideShowView::addMouseListener );
}
void EventMultiplexer::removeClickHandler(
const MouseEventHandlerSharedPtr& rHandler )
{
mpImpl->maMouseClickHandlers.remove(
EventMultiplexerImpl::ImplMouseHandlers::container_type::value_type(
rHandler,
0 .0 ) );
if ( !mpImpl->isMouseListenerRegistered() )
mpImpl->forEachView( &presentation::XSlideShowView::removeMouseListener );
}
void EventMultiplexer::addDoubleClickHandler(
const MouseEventHandlerSharedPtr& rHandler,
double nPriority )
{
mpImpl->addMouseHandler(
mpImpl->maMouseDoubleClickHandlers,
rHandler,
nPriority,
mpImpl->isMouseListenerRegistered()
? nullptr
: &presentation::XSlideShowView::addMouseListener );
}
void EventMultiplexer::removeDoubleClickHandler(
const MouseEventHandlerSharedPtr& rHandler )
{
mpImpl->maMouseDoubleClickHandlers.remove(
EventMultiplexerImpl::ImplMouseHandlers::container_type::value_type(
rHandler,
0 .0 ) );
if ( !mpImpl->isMouseListenerRegistered() )
mpImpl->forEachView( &presentation::XSlideShowView::removeMouseListener );
}
void EventMultiplexer::addMouseMoveHandler(
const MouseEventHandlerSharedPtr& rHandler,
double nPriority )
{
mpImpl->addMouseHandler(
mpImpl->maMouseMoveHandlers,
rHandler,
nPriority,
mpImpl->maMouseMoveHandlers.isEmpty()
? &presentation::XSlideShowView::addMouseMotionListener
: nullptr );
}
void EventMultiplexer::removeMouseMoveHandler(
const MouseEventHandlerSharedPtr& rHandler )
{
mpImpl->maMouseMoveHandlers.remove(
EventMultiplexerImpl::ImplMouseHandlers::container_type::value_type(
rHandler,
0 .0 ) );
if ( mpImpl->maMouseMoveHandlers.isEmpty() )
mpImpl->forEachView(
&presentation::XSlideShowView::removeMouseMotionListener );
}
void EventMultiplexer::addHyperlinkHandler( const HyperlinkHandlerSharedPtr& rHandler,
double nPriority )
{
mpImpl->maHyperlinkHandlers.addSorted(
EventMultiplexerImpl::ImplHyperLinkHandlers::container_type::value_type(
rHandler,
nPriority) );
}
void EventMultiplexer::removeHyperlinkHandler( const HyperlinkHandlerSharedPtr& rHandler )
{
mpImpl->maHyperlinkHandlers.remove(
EventMultiplexerImpl::ImplHyperLinkHandlers::container_type::value_type(
rHandler,
0 .0 ) );
}
void EventMultiplexer::notifyShapeListenerAdded(
const uno::Reference<drawing::XShape>& xShape )
{
mpImpl->maShapeListenerHandlers.applyAll(
[&xShape]( const ShapeListenerEventHandlerSharedPtr& pHandler )
{ return pHandler->listenerAdded( xShape ); } );
}
void EventMultiplexer::notifyShapeListenerRemoved(
const uno::Reference<drawing::XShape>& xShape )
{
mpImpl->maShapeListenerHandlers.applyAll(
[&xShape]( const ShapeListenerEventHandlerSharedPtr& pHandler )
{ return pHandler->listenerRemoved( xShape ); } );
}
void EventMultiplexer::notifyUserPaintColor( RGBColor const & rUserColor )
{
mpImpl->maUserPaintEventHandlers.applyAll(
[&rUserColor]( const UserPaintEventHandlerSharedPtr& pHandler )
{ return pHandler->colorChanged( rUserColor ); } );
}
void EventMultiplexer::notifyUserPaintStrokeWidth( double rUserStrokeWidth )
{
mpImpl->maUserPaintEventHandlers.applyAll(
[&rUserStrokeWidth]( const UserPaintEventHandlerSharedPtr& pHandler )
{ return pHandler->widthChanged( rUserStrokeWidth ); } );
}
void EventMultiplexer::notifyUserPaintDisabled()
{
mpImpl->maUserPaintEventHandlers.applyAll(
std::mem_fn(&UserPaintEventHandler::disable));
}
void EventMultiplexer::notifySwitchPenMode(){
mpImpl->maUserPaintEventHandlers.applyAll(
std::mem_fn(&UserPaintEventHandler::switchPenMode));
}
void EventMultiplexer::notifySwitchEraserMode(){
mpImpl->maUserPaintEventHandlers.applyAll(
std::mem_fn(&UserPaintEventHandler::switchEraserMode));
}
//adding erasing all ink features with UserPaintOverlay
void EventMultiplexer::notifyEraseAllInk( bool bEraseAllInk )
{
mpImpl->maUserPaintEventHandlers.applyAll(
[&bEraseAllInk]( const UserPaintEventHandlerSharedPtr& pHandler )
{ return pHandler->eraseAllInkChanged( bEraseAllInk ); } );
}
//adding erasing features with UserPaintOverlay
void EventMultiplexer::notifyEraseInkWidth( sal_Int32 rEraseInkSize )
{
mpImpl->maUserPaintEventHandlers.applyAll(
[&rEraseInkSize]( const UserPaintEventHandlerSharedPtr& pHandler )
{ return pHandler->eraseInkWidthChanged( rEraseInkSize ); } );
}
bool EventMultiplexer::notifyNextEffect()
{
return mpImpl->notifyNextEffect();
}
void EventMultiplexer::notifySlideStartEvent()
{
mpImpl->maSlideStartHandlers.applyAll(
std::mem_fn(&EventHandler::handleEvent) );
}
bool EventMultiplexer::notifySlideEndEvent()
{
return mpImpl->maSlideEndHandlers.applyAll(
std::mem_fn(&EventHandler::handleEvent) );
}
bool EventMultiplexer::notifyAnimationStart(
const AnimationNodeSharedPtr& rNode )
{
return EventMultiplexerImpl::notifyAllAnimationHandlers( mpImpl->maAnimationStartHandlers,
rNode );
}
bool EventMultiplexer::notifyAnimationEnd(
const AnimationNodeSharedPtr& rNode )
{
return EventMultiplexerImpl::notifyAllAnimationHandlers( mpImpl->maAnimationEndHandlers,
rNode );
}
bool EventMultiplexer::notifySlideAnimationsEnd()
{
return mpImpl->maSlideAnimationsEndHandlers.applyAll(
std::mem_fn(&EventHandler::handleEvent));
}
bool EventMultiplexer::notifyAudioStopped(
const AnimationNodeSharedPtr& rNode )
{
return EventMultiplexerImpl::notifyAllAnimationHandlers(
mpImpl->maAudioStoppedHandlers,
rNode );
}
bool EventMultiplexer::notifyCommandStopAudio(
const AnimationNodeSharedPtr& rNode )
{
return EventMultiplexerImpl::notifyAllAnimationHandlers(
mpImpl->maCommandStopAudioHandlers,
rNode );
}
void EventMultiplexer::notifyPauseMode( bool bPauseShow )
{
mpImpl->maPauseHandlers.applyAll(
[&bPauseShow]( const PauseEventHandlerSharedPtr& pHandler )
{ return pHandler->handlePause( bPauseShow ); } );
}
void EventMultiplexer::notifyViewAdded( const UnoViewSharedPtr& rView )
{
ENSURE_OR_THROW( rView, "EventMultiplexer::notifyViewAdded(): Invalid view" );
// register event listener
uno::Reference<presentation::XSlideShowView> const rUnoView(
rView->getUnoView() );
if ( mpImpl->isMouseListenerRegistered() )
rUnoView->addMouseListener(
mpImpl->mxListener );
if ( !mpImpl->maMouseMoveHandlers.isEmpty() )
rUnoView->addMouseMotionListener(
mpImpl->mxListener );
mpImpl->maViewHandlers.applyAll(
[&rView]( const ViewEventHandlerWeakPtr& pHandler )
{ return pHandler.lock()->viewAdded( rView ); } );
}
void EventMultiplexer::notifyViewRemoved( const UnoViewSharedPtr& rView )
{
ENSURE_OR_THROW( rView,
"EventMultiplexer::removeView(): Invalid view" );
// revoke event listeners
uno::Reference<presentation::XSlideShowView> const rUnoView(
rView->getUnoView() );
if ( mpImpl->isMouseListenerRegistered() )
rUnoView->removeMouseListener(
mpImpl->mxListener );
if ( !mpImpl->maMouseMoveHandlers.isEmpty() )
rUnoView->removeMouseMotionListener(
mpImpl->mxListener );
mpImpl->maViewHandlers.applyAll(
[&rView]( const ViewEventHandlerWeakPtr& pHandler )
{ return pHandler.lock()->viewRemoved( rView ); } );
}
void EventMultiplexer::notifyViewChanged( const UnoViewSharedPtr& rView )
{
mpImpl->maViewHandlers.applyAll(
[&rView]( const ViewEventHandlerWeakPtr& pHandler )
{ return pHandler.lock()->viewChanged( rView ); } );
}
void EventMultiplexer::notifyViewChanged( const uno::Reference<presentation::XSlideShowView>& xView )
{
UnoViewSharedPtr pView( mpImpl->findUnoView(xView) );
if ( !pView )
return ; // view not registered here
notifyViewChanged( pView );
}
void EventMultiplexer::notifyViewsChanged()
{
mpImpl->maViewHandlers.applyAll(
std::mem_fn( &ViewEventHandler::viewsChanged ));
}
void EventMultiplexer::notifyViewClobbered(
const uno::Reference<presentation::XSlideShowView>& xView )
{
UnoViewSharedPtr pView( mpImpl->findUnoView(xView) );
if ( !pView )
return ; // view not registered here
mpImpl->maViewRepaintHandlers.applyAll(
[&pView]( const ViewRepaintHandlerSharedPtr& pHandler )
{ return pHandler->viewClobbered( pView ); } );
}
void EventMultiplexer::notifyHyperlinkClicked(
OUString const & hyperLink )
{
mpImpl->maHyperlinkHandlers.apply(
[&hyperLink]( const PrioritizedHandlerEntry< HyperlinkHandler >& pHandler )
{ return pHandler.getHandler()->handleHyperlink( hyperLink ); } );
}
basegfx::B2DPoint EventMultiplexer::toMatrixPoint(const uno::Reference<uno::XInterface>& xInterface,
const basegfx::B2DPoint& pnt)
{
uno::Reference<presentation::XSlideShowView> xView(xInterface, uno::UNO_QUERY_THROW);
return mpImpl->toMatrixPoint(xView, pnt);
}
basegfx::B2DPoint EventMultiplexer::toNormalPoint(const uno::Reference<uno::XInterface>& xInterface,
const basegfx::B2DPoint& pnt)
{
uno::Reference<presentation::XSlideShowView> xView(xInterface, uno::UNO_QUERY_THROW);
return mpImpl->toNormalPoint(xView, pnt);
}
} // namespace presentation
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Messung V0.5 in Prozent C=94 H=96 G=94
¤ Dauer der Verarbeitung: 0.19 Sekunden
(vorverarbeitet am 2026-09-29)
¤
*© Formatika GbR, Deutschland
2026-10-09
Neuigkeiten
Aktuelles
Motto des Tages
Open Source Software
Jenseits des Üblichen ....
Besucherstatistik
Statistik
#Sources=1126438
#Domains=1867298