/************************************************************************* * * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: eventmultiplexer.cxx,v $ * * $Revision: 1.8 $ * * last change: $Author: rt $ $Date: 2006-07-26 07:25:16 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. * * * GNU Lesser General Public License Version 2.1 * ============================================= * Copyright 2005 by Sun Microsystems, Inc. * 901 San Antonio Road, Palo Alto, CA 94303, USA * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * ************************************************************************/ // must be first #include "canvas/debug.hxx" #include "tools.hxx" #include "eventmultiplexer.hxx" #include "com/sun/star/awt/SystemPointer.hpp" #include "com/sun/star/awt/XWindow.hpp" #include "com/sun/star/awt/MouseButton.hpp" #include "com/sun/star/presentation/XSlideShowView.hpp" #include "basegfx/numeric/ftools.hxx" #include "delayevent.hxx" #include "boost/bind.hpp" #include #include #include namespace css = ::com::sun::star; using namespace css; /* Implementation of EventMultiplexer class */ namespace presentation { namespace internal { template class EventMultiplexer::PrioritizedHandlerEntry { typedef PrioritizedHandlerEntry thisT; typedef boost::shared_ptr HandlerSharedPtrT; HandlerSharedPtrT m_pHandler; double m_nPrio; public: PrioritizedHandlerEntry( HandlerSharedPtrT const& pHandler, double nPrio ) : m_pHandler(pHandler), m_nPrio(nPrio) {} HandlerSharedPtrT const& getHandler() const { return m_pHandler; } /// To sort according to priority bool operator<( thisT const& rRHS ) const { // reversed order - high prioritized entries // should be at the beginning of the queue return m_nPrio > rRHS.m_nPrio; } /// To permit ::std::remove in removeHandler template bool operator==( HandlerSharedPtrT const& rRHS ) const { return m_pHandler == rRHS; } }; template bool EventMultiplexer::notifyAllHandlers( ContainerT const& rContainer, FuncT const& func, bool bOperateOnCopy ) { if (bOperateOnCopy) { osl::ClearableMutexGuard guard( m_aMutex ); // generate a local copy of all handlers, since we have to // release the object mutex before firing. ContainerT const local( rContainer ); guard.clear(); // true: at least one handler returned true // false: not a single handler returned true return (std::count_if( local.begin(), local.end(), func ) > 0); } else { // true: at least one handler returned true // false: not a single handler returned true return (std::count_if( rContainer.begin(), rContainer.end(), func ) >0); } } template bool EventMultiplexer::notifySingleHandler( ContainerT const& rContainer, FuncT const& func, bool bOperateOnCopy ) { // fire event on handlers, try in order of precedence. If // one high-priority handler rejects the event // (i.e. returns false), try next handler. if (bOperateOnCopy) { osl::ClearableMutexGuard guard( m_aMutex ); // generate a local copy of all handlers, since we have to // release the object mutex before firing. ContainerT const localHandlers( rContainer ); guard.clear(); typename ContainerT::const_iterator const iEnd( localHandlers.end() ); // true: a handler in this queue processed the event // false: no handler in this queue finally processed the event return (std::find_if( localHandlers.begin(), iEnd, func ) != iEnd); } else { typename ContainerT::const_iterator const iEnd( rContainer.end() ); // true: a handler in this queue processed the event // false: no handler in this queue finally processed the event return (std::find_if( rContainer.begin(), iEnd, func ) != iEnd); } } template void EventMultiplexer::addHandler( ContainerT & rContainer, boost::shared_ptr const& pHandler ) { ENSURE_AND_THROW( pHandler.get() != 0, "EventMultiplexer::addHandler(): Invalid handler" ); osl::MutexGuard const guard( m_aMutex ); rContainer.push_back( pHandler ); } template void EventMultiplexer::addPrioritizedHandler( ContainerT & rContainer, boost::shared_ptr const& pHandler, double nPriority ) { ENSURE_AND_THROW( pHandler.get() != 0, "EventMultiplexer::addHandler(): Invalid handler" ); osl::MutexGuard const guard( m_aMutex ); // insert into queue (not sorted yet) rContainer.push_back( typename ContainerT::value_type( pHandler, nPriority ) ); if (rContainer.size() > 1) { // element was inserted, but now we have to keep the // entries sorted std::inplace_merge( rContainer.begin(), rContainer.end() - 1, rContainer.end() ); } // no need to call inplace_merge otherwise, added // entry is the only one on the heap. } template< typename Container, typename Handler > void EventMultiplexer::removeHandler( Container & rContainer, const ::boost::shared_ptr& rHandler ) { ::osl::MutexGuard aGuard( m_aMutex ); ENSURE_AND_THROW( rHandler.get(), "EventMultiplexer::removeHandler(): Invalid handler" ); const typename Container::iterator aEnd( rContainer.end() ); rContainer.erase( ::std::remove(rContainer.begin(), aEnd, rHandler), aEnd ); } template void EventMultiplexer::forEachView( XSlideShowViewFunc pViewMethod ) { if (pViewMethod) { // (un)register mouse listener on all views for( UnoViewVector::const_iterator aIter( maViews.begin() ), aEnd( maViews.end() ); aIter != aEnd; ++aIter ) { ((*aIter)->getUnoView().get()->*pViewMethod)( this ); } } } template< typename RegisterFunction > void EventMultiplexer::addMouseHandler( ImplMouseHandlers& rHandlerContainer, const MouseEventHandlerSharedPtr& rHandler, double nPriority, RegisterFunction pRegisterListener ) { ::osl::MutexGuard aGuard( m_aMutex ); ENSURE_AND_THROW( rHandler.get(), "EventMultiplexer::addMouseHandler(): Invalid handler" ); // register mouse listener on all views forEachView( pRegisterListener ); // sort into container: addPrioritizedHandler( rHandlerContainer, rHandler, nPriority ); } bool EventMultiplexer::isMouseListenerRegistered() const { return !(maMouseClickHandlers.empty() && maMouseDoubleClickHandlers.empty()); } void EventMultiplexer::tick() { ::osl::MutexGuard aGuard( m_aMutex ); if( !mbIsAutoMode ) return; // this event is just a left-over, ignore notifyNextEffect(); if( !maNextEffectHandlers.empty() ) { // still handlers left, schedule next timeout // event. Will also set mbIsTickEventOn back to true scheduleTick(); } } void EventMultiplexer::scheduleTick() { // TODO(Q3): make robust (no boost::ref()) when // get_pointer(uno::Ref...) is available EventSharedPtr pEvent( makeDelay( boost::bind( &EventMultiplexer::tick, this ), mnTimeout ) ); // 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 EventMultiplexer::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(); } void EventMultiplexer::implSetMouseCursor( sal_Int16 nCursor ) const { // change all views to the requested cursor ID std::for_each( maViews.begin(), maViews.end(), boost::bind( &View::setMouseCursor, _1, nCursor ) ); } bool EventMultiplexer::addView( const UnoViewSharedPtr& rView ) { ENSURE_AND_THROW( rView.get(), "EventMultiplexer::addView(): Invalid view"); ::osl::MutexGuard aGuard( m_aMutex ); // check whether same view is already added const UnoViewVector::iterator aEnd( maViews.end() ); // already added? if( ::std::find( maViews.begin(), aEnd, rView ) != aEnd ) { // yes, nothing to do return false; } maViews.push_back( rView ); return true; } bool EventMultiplexer::removeView( const UnoViewSharedPtr& rView ) { ENSURE_AND_THROW( rView.get(), "EventMultiplexer::removeView(): Invalid view" ); ::osl::MutexGuard aGuard( m_aMutex ); // check whether same view is already added const UnoViewVector::iterator aEnd( maViews.end() ); UnoViewVector::iterator aIter; // view added? if( (aIter=::std::find( maViews.begin(), aEnd, rView )) == aEnd ) { // nope, nothing to do return false; } // revoke event listeners uno::Reference const rUnoView( rView->getUnoView() ); if( isMouseListenerRegistered() ) rUnoView->removeMouseListener( this ); if( !maMouseMoveHandlers.empty() ) rUnoView->removeMouseMotionListener( this ); // actually erase from container maViews.erase( aIter ); return true; } void EventMultiplexer::clear() { ::osl::MutexGuard aGuard( m_aMutex ); // deregister from all views. if( isMouseListenerRegistered() ) { for( UnoViewVector::iterator aIter=maViews.begin(), aEnd=maViews.end(); aIter!=aEnd; ++aIter ) { (*aIter)->getUnoView()->removeMouseListener( this ); } } if( !maMouseMoveHandlers.empty() ) { for( UnoViewVector::iterator aIter=maViews.begin(), aEnd=maViews.end(); aIter!=aEnd; ++aIter ) { (*aIter)->getUnoView()->removeMouseMotionListener( this ); } } // release all references maViews.clear(); maNextEffectHandlers.clear(); maSlideStartHandlers.clear(); maSlideEndHandlers.clear(); maAnimationStartHandlers.clear(); maAnimationEndHandlers.clear(); maSlideAnimationsEndHandlers.clear(); maAudioStoppedHandlers.clear(); maCommandStopAudioHandlers.clear(); maPauseHandlers.clear(); maMouseClickHandlers.clear(); maMouseDoubleClickHandlers.clear(); maMouseMoveHandlers.clear(); maHyperlinkHandlers.clear(); mpLayerManager.reset(); } void EventMultiplexer::setMouseCursor( sal_Int16 nCursor ) { ::osl::MutexGuard aGuard( m_aMutex ); mnMouseCursor = nCursor; implSetMouseCursor( mnMouseCursor ); } void EventMultiplexer::setVolatileMouseCursor( sal_Int16 nCursor ) { ::osl::MutexGuard aGuard( m_aMutex ); // only change, if volatile cursor is not already // set. This effectively prioritizes handlers with the // highest priority (otherwise, the handler with the // lowest prio would determine the mouse cursor - // unwanted). if( mnVolatileMouseCursor == -1 ) mnVolatileMouseCursor = nCursor; } void EventMultiplexer::setLayerManager( const LayerManagerSharedPtr& rMgr ) { mpLayerManager = rMgr; } void EventMultiplexer::updateScreenContent( bool bForceUpdate ) { // perform screen update (either if we're forced to do it, // or if the layer manager signals that it needs one). if( bForceUpdate || (mpLayerManager.get() && mpLayerManager->isUpdatePending() ) ) { // call update() on the registered // LayerManager. This will only update the // backbuffer, not flush anything to screen if( mpLayerManager.get() ) mpLayerManager->update(); // call updateScreen() on all registered views (which // will copy the backbuffers to the front). Do NOT use // LayerManager::updateScreen(), we might need screen // updates independent from a valid LayerManager! ::std::for_each( maViews.begin(), maViews.end(), ::boost::mem_fn( &View::updateScreen ) ); } } void EventMultiplexer::setAutomaticMode( bool bIsAuto ) { ::osl::MutexGuard aGuard( m_aMutex ); if( bIsAuto == mbIsAutoMode ) return; // no change, nothing to do mbIsAutoMode = bIsAuto; handleTicks(); } bool EventMultiplexer::getAutomaticMode() const { ::osl::MutexGuard aGuard( m_aMutex ); return mbIsAutoMode; } void EventMultiplexer::setAutomaticTimeout( double nTimeout ) { ::osl::MutexGuard aGuard( m_aMutex ); mnTimeout = nTimeout; } double EventMultiplexer::getAutomaticTimeout() const { ::osl::MutexGuard aGuard( m_aMutex ); return mnTimeout; } void EventMultiplexer::addNextEffectHandler( EventHandlerSharedPtr const& rHandler, double nPriority ) { addPrioritizedHandler( maNextEffectHandlers, rHandler, nPriority ); // Enable tick events, if not done already handleTicks(); } void EventMultiplexer::removeNextEffectHandler( const EventHandlerSharedPtr& rHandler ) { removeHandler( maNextEffectHandlers, rHandler ); } void EventMultiplexer::addSlideStartHandler( const EventHandlerSharedPtr& rHandler ) { addHandler( maSlideStartHandlers, rHandler ); } void EventMultiplexer::removeSlideStartHandler( const EventHandlerSharedPtr& rHandler ) { removeHandler( maSlideStartHandlers, rHandler ); } void EventMultiplexer::addSlideEndHandler( const EventHandlerSharedPtr& rHandler ) { addHandler( maSlideEndHandlers, rHandler ); } void EventMultiplexer::removeSlideEndHandler( const EventHandlerSharedPtr& rHandler ) { removeHandler( maSlideEndHandlers, rHandler ); } void EventMultiplexer::addAnimationStartHandler( const AnimationEventHandlerSharedPtr& rHandler ) { addHandler( maAnimationStartHandlers, rHandler ); } void EventMultiplexer::removeAnimationStartHandler( const AnimationEventHandlerSharedPtr& rHandler ) { removeHandler( maAnimationStartHandlers, rHandler ); } void EventMultiplexer::addAnimationEndHandler( const AnimationEventHandlerSharedPtr& rHandler ) { addHandler( maAnimationEndHandlers, rHandler ); } void EventMultiplexer::removeAnimationEndHandler( const AnimationEventHandlerSharedPtr& rHandler ) { removeHandler( maAnimationEndHandlers, rHandler ); } void EventMultiplexer::addSlideAnimationsEndHandler( const EventHandlerSharedPtr& rHandler ) { addHandler( maSlideAnimationsEndHandlers, rHandler ); } void EventMultiplexer::removeSlideAnimationsEndHandler( const EventHandlerSharedPtr& rHandler ) { removeHandler( maSlideAnimationsEndHandlers, rHandler ); } void EventMultiplexer::addAudioStoppedHandler( const AnimationEventHandlerSharedPtr& rHandler ) { addHandler( maAudioStoppedHandlers, rHandler ); } void EventMultiplexer::removeAudioStoppedHandler( const AnimationEventHandlerSharedPtr& rHandler ) { removeHandler( maAudioStoppedHandlers, rHandler ); } void EventMultiplexer::addCommandStopAudioHandler( const AnimationEventHandlerSharedPtr& rHandler ) { addHandler( maCommandStopAudioHandlers, rHandler ); } void EventMultiplexer::removeCommandStopAudioHandler( const AnimationEventHandlerSharedPtr& rHandler ) { removeHandler( maCommandStopAudioHandlers, rHandler ); } void EventMultiplexer::addPauseHandler( const PauseEventHandlerSharedPtr& rHandler ) { addHandler( maPauseHandlers, rHandler ); } void EventMultiplexer::removePauseHandler( const PauseEventHandlerSharedPtr& rHandler ) { removeHandler( maPauseHandlers, rHandler ); } void EventMultiplexer::addClickHandler( const MouseEventHandlerSharedPtr& rHandler, double nPriority ) { addMouseHandler( maMouseClickHandlers, rHandler, nPriority, isMouseListenerRegistered() ? NULL : &css::presentation::XSlideShowView::addMouseListener ); } void EventMultiplexer::removeClickHandler( const MouseEventHandlerSharedPtr& rHandler ) { ::osl::MutexGuard aGuard( m_aMutex ); removeHandler( maMouseClickHandlers, rHandler ); if( !isMouseListenerRegistered() ) { forEachView( &css::presentation::XSlideShowView::removeMouseListener ); } } void EventMultiplexer::addDoubleClickHandler( const MouseEventHandlerSharedPtr& rHandler, double nPriority ) { addMouseHandler( maMouseDoubleClickHandlers, rHandler, nPriority, isMouseListenerRegistered() ? NULL : &css::presentation::XSlideShowView::addMouseListener ); } void EventMultiplexer::removeDoubleClickHandler( const MouseEventHandlerSharedPtr& rHandler ) { ::osl::MutexGuard aGuard( m_aMutex ); removeHandler( maMouseDoubleClickHandlers, rHandler ); if( !isMouseListenerRegistered() ) { forEachView( &css::presentation::XSlideShowView::removeMouseListener ); } } void EventMultiplexer::addMouseMoveHandler( const MouseEventHandlerSharedPtr& rHandler, double nPriority ) { addMouseHandler( maMouseMoveHandlers, rHandler, nPriority, maMouseMoveHandlers.empty() ? &css::presentation::XSlideShowView::addMouseMotionListener : NULL ); } void EventMultiplexer::removeMouseMoveHandler( const MouseEventHandlerSharedPtr& rHandler ) { ::osl::MutexGuard aGuard( m_aMutex ); removeHandler( maMouseMoveHandlers, rHandler ); if( maMouseMoveHandlers.empty() ) { forEachView( &css::presentation::XSlideShowView::removeMouseMotionListener ); } } void EventMultiplexer::addHyperlinkHandler( HyperLinkHandlerFunc const& func, HandlerId id ) { osl::MutexGuard const guard(m_aMutex); maHyperlinkHandlers[id] = func; // second add will overwrite previous func } void EventMultiplexer::removeHyperlinkHandler( HandlerId id ) { osl::MutexGuard const guard(m_aMutex); maHyperlinkHandlers.erase(id); } bool EventMultiplexer::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 notifySingleHandler( maNextEffectHandlers, boost::bind( &EventHandler::handleEvent, boost::bind( &ImplNextEffectHandlers::value_type::getHandler, _1 ) ) ); } bool EventMultiplexer::notifySlideStartEvent() { return notifyAllEventHandlers( maSlideStartHandlers ); } bool EventMultiplexer::notifySlideEndEvent() { return notifyAllEventHandlers( maSlideEndHandlers ); } bool EventMultiplexer::notifyAnimationStart( const AnimationNodeSharedPtr& rNode ) { return notifyAllAnimationHandlers( maAnimationStartHandlers, rNode ); } bool EventMultiplexer::notifyAnimationEnd( const AnimationNodeSharedPtr& rNode ) { return notifyAllAnimationHandlers( maAnimationEndHandlers, rNode ); } bool EventMultiplexer::notifySlideAnimationsEnd() { return notifyAllEventHandlers( maSlideAnimationsEndHandlers ); } bool EventMultiplexer::notifyAudioStopped( const AnimationNodeSharedPtr& rNode ) { return notifyAllAnimationHandlers( maAudioStoppedHandlers, rNode ); } bool EventMultiplexer::notifyCommandStopAudio( const AnimationNodeSharedPtr& rNode ) { return notifyAllAnimationHandlers( maCommandStopAudioHandlers, rNode ); } bool EventMultiplexer::notifyPauseMode( bool bPauseShow ) { return notifyAllHandlers( maPauseHandlers, boost::bind( &PauseEventHandler::handlePause, _1, bPauseShow ) ); } struct EventMultiplexer::HyperLinkNotifier { rtl::OUString const& m_rLink; HyperLinkNotifier( rtl::OUString const& link ) : m_rLink(link) {} bool operator()( ImplHyperLinkHandlers::value_type const& v ) const { return v.second( m_rLink ); } }; bool EventMultiplexer::notifyHyperlinkClicked( rtl::OUString const& hyperLink ) { return notifySingleHandler( maHyperlinkHandlers, HyperLinkNotifier( hyperLink ) ); } void EventMultiplexer::disposing() { // release all references clear(); WeakComponentImplHelperBase::disposing(); } // XMouseListener implementation void SAL_CALL EventMultiplexer::disposing( const lang::EventObject& rSource ) throw (uno::RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); // remove given event source for( UnoViewVector::iterator aIter=maViews.begin(), aEnd=maViews.end(); aIter!=aEnd; ++aIter ) { if( (*aIter)->getUnoView() == rSource.Source ) { // one instance found, remove aIter = maViews.erase( aIter ); aEnd = maViews.end(); // erase might invalidate all iterators! } } } bool EventMultiplexer::notifyMouseHandlers( const ImplMouseHandlers& rQueue, bool (MouseEventHandler::*pHandlerMethod)( const awt::MouseEvent& ), const awt::MouseEvent& e ) { uno::Reference xView( e.Source, uno::UNO_QUERY ); ENSURE_AND_RETURN( xView.is(), "EventMultiplexer::notifyHandlers(): " "event source is not an XSlideShowView" ); // find corresponding view (to mouse position into user coordinate space) UnoViewVector::iterator aIter; const UnoViewVector::iterator aEnd( maViews.end() ); if( (aIter=::std::find_if( maViews.begin(), aEnd, boost::bind( std::equal_to< uno::Reference< css::presentation::XSlideShowView > >(), boost::cref( xView ), boost::bind( &UnoView::getUnoView, _1 ) ) ) ) == aEnd) { ENSURE_AND_RETURN( 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_AND_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 notifySingleHandler( rQueue, boost::bind( pHandlerMethod, boost::bind( &ImplMouseHandlers::value_type::getHandler, _1 ), aEvent ), false /* no separate copy: already operating on copy made in implMouseXXX() */ ); } void EventMultiplexer::implMousePressed( const awt::MouseEvent& e ) { osl::ClearableMutexGuard guard( m_aMutex ); // generate a local copy of all handlers, since we have to // release the object mutex before firing. ImplMouseHandlers const localDoubleClickHandlers( maMouseDoubleClickHandlers ); ImplMouseHandlers const localClickHandlers( maMouseClickHandlers ); guard.clear(); // fire double-click events for every second click sal_Int32 nCurrClickCount = e.ClickCount; while( nCurrClickCount > 1 && notifyMouseHandlers( localDoubleClickHandlers, &MouseEventHandler::handleMousePressed, e ) ) { nCurrClickCount -= 2; } // fire single-click events for all remaining clicks while( nCurrClickCount > 0 && notifyMouseHandlers( localClickHandlers, &MouseEventHandler::handleMousePressed, e ) ) { --nCurrClickCount; } } void EventMultiplexer::implMouseReleased( const awt::MouseEvent& e ) { // generate a local copy of all handlers, since we have to // release the object mutex before firing. osl::ClearableMutexGuard guard( m_aMutex ); ImplMouseHandlers const localDoubleClickHandlers( maMouseDoubleClickHandlers ); ImplMouseHandlers const localClickHandlers( maMouseClickHandlers ); guard.clear(); // fire double-click events for every second click sal_Int32 nCurrClickCount = e.ClickCount; while( nCurrClickCount > 1 && notifyMouseHandlers( localDoubleClickHandlers, &MouseEventHandler::handleMouseReleased, e ) ) { nCurrClickCount -= 2; } // fire single-click events for all remaining clicks while( nCurrClickCount > 0 && notifyMouseHandlers( localClickHandlers, &MouseEventHandler::handleMouseReleased, e ) ) { --nCurrClickCount; } } void EventMultiplexer::implMouseDragged( const awt::MouseEvent& e ) { osl::ResettableMutexGuard guard( m_aMutex ); // generate a local copy of all handlers, since we have to // release the object mutex before firing. ImplMouseHandlers const localHandlers( maMouseMoveHandlers ); guard.clear(); notifyMouseHandlers( localHandlers, &MouseEventHandler::handleMouseDragged, e ); // re-acquire mutex guard.reset(); if( mnVolatileMouseCursor != -1 ) { // handlers requested a volatile mouse cursor - set // one mnLastVolatileMouseCursor = mnVolatileMouseCursor; implSetMouseCursor( mnVolatileMouseCursor ); mnVolatileMouseCursor = -1; } else if( mnMouseCursor != mnLastVolatileMouseCursor ) { // handlers did not request a volatile mouse cursor - // clear to default, if necessary implSetMouseCursor( mnMouseCursor ); mnLastVolatileMouseCursor = mnMouseCursor; } } void EventMultiplexer::implMouseMoved( const awt::MouseEvent& e ) { osl::ResettableMutexGuard guard( m_aMutex ); // generate a local copy of all handlers, since we have to // release the object mutex before firing. ImplMouseHandlers const localHandlers( maMouseMoveHandlers ); guard.clear(); notifyMouseHandlers( localHandlers, &MouseEventHandler::handleMouseMoved, e ); // re-acquire mutex guard.reset(); if( mnVolatileMouseCursor != -1 ) { // handlers requested a volatile mouse cursor - set // one mnLastVolatileMouseCursor = mnVolatileMouseCursor; implSetMouseCursor( mnVolatileMouseCursor ); mnVolatileMouseCursor = -1; } else if( mnMouseCursor != mnLastVolatileMouseCursor ) { // handlers did not request a volatile mouse cursor - // clear to default, if necessary implSetMouseCursor( mnMouseCursor ); mnLastVolatileMouseCursor = mnMouseCursor; } } void SAL_CALL EventMultiplexer::mousePressed( const awt::MouseEvent& e ) throw (uno::RuntimeException) { osl::MutexGuard const guard( m_aMutex ); // notify mouse press. Don't call handlers directly, this // might not be the main thread! mrEventQueue.addEvent( makeEvent( boost::bind( &EventMultiplexer::implMousePressed, this, e ) ) ); } void SAL_CALL EventMultiplexer::mouseReleased( const awt::MouseEvent& e ) throw (uno::RuntimeException) { osl::MutexGuard const guard( m_aMutex ); // notify mouse release. Don't call handlers directly, // this might not be the main thread! mrEventQueue.addEvent( makeEvent( boost::bind( &EventMultiplexer::implMouseReleased, this, e ) ) ); } void SAL_CALL EventMultiplexer::mouseEntered( const awt::MouseEvent& e ) throw (uno::RuntimeException) { // not used here } void SAL_CALL EventMultiplexer::mouseExited( const awt::MouseEvent& e ) throw (uno::RuntimeException) { // not used here } // XMouseMotionListener implementation void SAL_CALL EventMultiplexer::mouseDragged( const awt::MouseEvent& e ) throw (uno::RuntimeException) { osl::MutexGuard const guard( m_aMutex ); // notify mouse drag. Don't call handlers directly, this // might not be the main thread! mrEventQueue.addEvent( makeEvent( boost::bind( &EventMultiplexer::implMouseDragged, this, e ) ) ); } void SAL_CALL EventMultiplexer::mouseMoved( const awt::MouseEvent& e ) throw (uno::RuntimeException) { osl::MutexGuard const guard( m_aMutex ); // notify mouse move. Don't call handlers directly, this // might not be the main thread! mrEventQueue.addEvent( makeEvent( boost::bind( &EventMultiplexer::implMouseMoved, this, e ) ) ); } EventMultiplexer::~EventMultiplexer() { // WeakComponentImplHelperBase calls disposing() upon destruction // if object has not been disposed yet. } EventMultiplexer::EventMultiplexer( EventQueue & rEventQueue ) : Listener_UnoBase( m_aMutex ), mrEventQueue( rEventQueue ), maViews(), maNextEffectHandlers(), maSlideStartHandlers(), maSlideEndHandlers(), maAnimationStartHandlers(), maAnimationEndHandlers(), maSlideAnimationsEndHandlers(), maAudioStoppedHandlers(), maCommandStopAudioHandlers(), maPauseHandlers(), maMouseClickHandlers(), maMouseDoubleClickHandlers(), maMouseMoveHandlers(), maHyperlinkHandlers(), mnTimeout( 0.0 ), mpTickEvent(), mnMouseCursor( awt::SystemPointer::ARROW ), mnVolatileMouseCursor( -1 ), mnLastVolatileMouseCursor( mnMouseCursor ), mbIsAutoMode( false ) { } rtl::Reference EventMultiplexer::create( EventQueue & rEventQueue ) { return new EventMultiplexer(rEventQueue); } } // namespace internal } // namespace presentation