1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
20 #include <slideshowviewimpl.hxx>
21 #include <slideshowimpl.hxx>
22 #include <osl/mutex.hxx>
24 #include <com/sun/star/awt/Pointer.hpp>
25 #include <com/sun/star/beans/XPropertySet.hpp>
27 #include <basegfx/polygon/b2dpolygon.hxx>
28 #include <basegfx/polygon/b2dpolygontools.hxx>
29 #include <basegfx/matrix/b2dhommatrixtools.hxx>
31 #include <cppcanvas/vclfactory.hxx>
32 #include <cppcanvas/basegfxfactory.hxx>
35 using ::com::sun::star::uno::UNO_QUERY
;
36 using ::com::sun::star::uno::XInterface
;
37 using ::com::sun::star::uno::Reference
;
38 using ::com::sun::star::uno::WeakReference
;
39 using ::com::sun::star::uno::RuntimeException
;
40 using ::com::sun::star::lang::XComponent
;
41 using ::com::sun::star::uno::Exception
;
42 using ::com::sun::star::presentation::XSlideShow
;
43 using ::com::sun::star::presentation::XSlideShowView
;
44 using ::com::sun::star::presentation::XShapeEventListener
;
45 using ::com::sun::star::presentation::XSlideShowListener
;
46 using ::comphelper::ImplementationReference
;
48 using namespace ::com::sun::star
;
53 ///////////////////////////////////////////////////////////////////////
54 // SlideShowViewListeners
55 ///////////////////////////////////////////////////////////////////////
57 SlideShowViewListeners::SlideShowViewListeners( ::osl::Mutex
& rMutex
)
62 void SlideShowViewListeners::addListener( const Reference
< util::XModifyListener
>& _rxListener
)
64 ::osl::MutexGuard
aGuard( mrMutex
);
66 WeakReference
< util::XModifyListener
> xWeak( _rxListener
);
67 if( std::find( maListeners
.begin(), maListeners
.end(), xWeak
) == maListeners
.end() )
68 maListeners
.push_back( xWeak
);
71 void SlideShowViewListeners::removeListener( const Reference
< util::XModifyListener
>& _rxListener
)
73 ::osl::MutexGuard
aGuard( mrMutex
);
75 WeakReference
< util::XModifyListener
> xWeak( _rxListener
);
76 ViewListenerVector::iterator
aIter( std::find( maListeners
.begin(), maListeners
.end(), xWeak
) );
77 if( aIter
!= maListeners
.end() )
78 maListeners
.erase( aIter
);
81 bool SlideShowViewListeners::notify( const lang::EventObject
& _rEvent
) throw( com::sun::star::uno::Exception
)
83 ::osl::MutexGuard
aGuard( mrMutex
);
85 ViewListenerVector::iterator
aIter( maListeners
.begin() );
86 while( aIter
!= maListeners
.end() )
88 Reference
< util::XModifyListener
> xListener( (*aIter
) );
91 xListener
->modified( _rEvent
);
96 aIter
= maListeners
.erase( aIter
);
102 void SlideShowViewListeners::disposing( const lang::EventObject
& _rEventSource
)
104 ::osl::MutexGuard
aGuard( mrMutex
);
106 ViewListenerVector::iterator
aIter( maListeners
.begin() );
107 while( aIter
!= maListeners
.end() )
109 Reference
< util::XModifyListener
> xListener( (*aIter
++) );
111 xListener
->disposing( _rEventSource
);
117 ///////////////////////////////////////////////////////////////////////
118 // SlideShowViewPaintListeners
119 ///////////////////////////////////////////////////////////////////////
121 SlideShowViewPaintListeners::SlideShowViewPaintListeners( ::osl::Mutex
& rMutex
)
122 : SlideShowViewPaintListeners_Base( rMutex
)
126 bool SlideShowViewPaintListeners::implTypedNotify( const Reference
< awt::XPaintListener
>& rListener
,
127 const awt::PaintEvent
& rEvent
) throw( uno::Exception
)
129 rListener
->windowPaint( rEvent
);
130 return true; // continue calling listeners
133 ///////////////////////////////////////////////////////////////////////
134 // SlideShowViewMouseListeners
135 ///////////////////////////////////////////////////////////////////////
137 SlideShowViewMouseListeners::SlideShowViewMouseListeners( ::osl::Mutex
& rMutex
) :
138 SlideShowViewMouseListeners_Base( rMutex
)
142 bool SlideShowViewMouseListeners::implTypedNotify( const Reference
< awt::XMouseListener
>& rListener
,
143 const WrappedMouseEvent
& rEvent
) throw( uno::Exception
)
145 switch( rEvent
.meType
)
147 case WrappedMouseEvent::PRESSED
:
148 rListener
->mousePressed( rEvent
.maEvent
);
151 case WrappedMouseEvent::RELEASED
:
152 rListener
->mouseReleased( rEvent
.maEvent
);
155 case WrappedMouseEvent::ENTERED
:
156 rListener
->mouseEntered( rEvent
.maEvent
);
159 case WrappedMouseEvent::EXITED
:
160 rListener
->mouseExited( rEvent
.maEvent
);
164 return true; // continue calling listeners
167 ///////////////////////////////////////////////////////////////////////
168 // SlideShowViewMouseMotionListeners
169 ///////////////////////////////////////////////////////////////////////
171 SlideShowViewMouseMotionListeners::SlideShowViewMouseMotionListeners( ::osl::Mutex
& rMutex
) :
172 SlideShowViewMouseMotionListeners_Base( rMutex
)
176 bool SlideShowViewMouseMotionListeners::implTypedNotify( const Reference
< awt::XMouseMotionListener
>& rListener
,
177 const WrappedMouseMotionEvent
& rEvent
) throw( uno::Exception
)
179 switch( rEvent
.meType
)
181 case WrappedMouseMotionEvent::DRAGGED
:
182 rListener
->mouseDragged( rEvent
.maEvent
);
185 case WrappedMouseMotionEvent::MOVED
:
186 rListener
->mouseMoved( rEvent
.maEvent
);
190 return true; // continue calling listeners
193 ///////////////////////////////////////////////////////////////////////
195 ///////////////////////////////////////////////////////////////////////
197 SlideShowView::SlideShowView( ShowWindow
& rOutputWindow
,
198 SdDrawDocument
* pDoc
,
199 AnimationMode eAnimationMode
,
200 SlideshowImpl
* pSlideShow
,
202 : SlideShowView_Base( m_aMutex
),
203 mpCanvas( ::cppcanvas::VCLFactory::getInstance().createSpriteCanvas( rOutputWindow
) ),
204 mxWindow( VCLUnoHelper::GetInterface( &rOutputWindow
), uno::UNO_QUERY_THROW
),
205 mxWindowPeer( mxWindow
, uno::UNO_QUERY_THROW
),
207 mpSlideShow( pSlideShow
),
208 mrOutputWindow( rOutputWindow
),
209 mpViewListeners( new SlideShowViewListeners( m_aMutex
) ),
210 mpPaintListeners( new SlideShowViewPaintListeners( m_aMutex
) ),
211 mpMouseListeners( new SlideShowViewMouseListeners( m_aMutex
) ),
212 mpMouseMotionListeners( new SlideShowViewMouseMotionListeners( m_aMutex
) ),
214 mbIsMouseMotionListener( false ),
215 meAnimationMode( eAnimationMode
),
216 mbFirstPaint( true ),
217 mbFullScreen( bFullScreen
),
218 mbMousePressedEaten( false )
223 /// Dispose all internal references
224 void SAL_CALL
SlideShowView::dispose() throw (RuntimeException
)
226 ::osl::MutexGuard
aGuard( m_aMutex
);
230 // deregister listeners
233 mxWindow
->removeWindowListener( this );
234 mxWindow
->removeMouseListener( this );
236 if( mbIsMouseMotionListener
)
237 mxWindow
->removeMouseMotionListener( this );
243 // clear all listener containers
244 disposing( lang::EventObject() );
247 WeakComponentImplHelperBase::dispose();
250 /// Disposing our broadcaster
251 void SAL_CALL
SlideShowView::disposing( const lang::EventObject
& ) throw(RuntimeException
)
253 ::osl::MutexGuard
aGuard( m_aMutex
);
255 // notify all listeners that _we_ are going down (send a disposing()),
256 // then delete listener containers:
257 lang::EventObject
const evt( static_cast<OWeakObject
*>(this) );
258 if (mpViewListeners
.get() != 0) {
259 mpViewListeners
->disposing( evt
);
260 mpViewListeners
.reset();
262 if (mpPaintListeners
.get() != 0) {
263 mpPaintListeners
->disposing( evt
);
264 mpPaintListeners
.reset();
266 if (mpMouseListeners
.get() != 0) {
267 mpMouseListeners
->disposing( evt
);
268 mpMouseListeners
.reset();
270 if (mpMouseMotionListeners
.get() != 0) {
271 mpMouseMotionListeners
->disposing( evt
);
272 mpMouseMotionListeners
.reset();
276 void SAL_CALL
SlideShowView::paint( const awt::PaintEvent
& e
) throw (RuntimeException
)
278 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
282 mbFirstPaint
= false;
283 SlideshowImpl
* pSlideShow
= mpSlideShow
;
286 pSlideShow
->onFirstPaint();
290 // Change event source, to enable listeners to match event
292 awt::PaintEvent
aEvent( e
);
293 aEvent
.Source
= static_cast< ::cppu::OWeakObject
* >( this );
294 mpPaintListeners
->notify( aEvent
);
295 updateimpl( aGuard
, mpSlideShow
); // warning: clears guard!
299 // XSlideShowView methods
300 Reference
< rendering::XSpriteCanvas
> SAL_CALL
SlideShowView::getCanvas( ) throw (RuntimeException
)
302 ::osl::MutexGuard
aGuard( m_aMutex
);
304 return mpCanvas
.get() ? mpCanvas
->getUNOSpriteCanvas() : Reference
< rendering::XSpriteCanvas
>();
307 void SAL_CALL
SlideShowView::clear() throw (::com::sun::star::uno::RuntimeException
)
309 // paint background in black
310 ::osl::MutexGuard
aGuard( m_aMutex
);
311 SolarMutexGuard aSolarGuard
;
313 // fill the bounds rectangle in black
314 // ----------------------------------
316 const Size
aWindowSize( mrOutputWindow
.GetSizePixel() );
318 ::basegfx::B2DPolygon
aPoly( ::basegfx::tools::createPolygonFromRect(
319 ::basegfx::B2DRectangle(0.0,0.0,
321 aWindowSize
.Height() ) ) );
322 ::cppcanvas::PolyPolygonSharedPtr
pPolyPoly(
323 ::cppcanvas::BaseGfxFactory::getInstance().createPolyPolygon( mpCanvas
, aPoly
) );
325 if( pPolyPoly
.get() )
327 pPolyPoly
->setRGBAFillColor( 0x000000FFU
);
332 geometry::AffineMatrix2D SAL_CALL
SlideShowView::getTransformation( ) throw (RuntimeException
)
334 ::osl::MutexGuard
aGuard( m_aMutex
);
335 SolarMutexGuard aSolarGuard
;
337 const Size
& rTmpSize( mrOutputWindow
.GetSizePixel() );
339 if (rTmpSize
.Width()<=0 || rTmpSize
.Height()<=0)
341 return geometry::AffineMatrix2D (1,0,0,0,1,0);
344 const Size
aWindowSize( mrOutputWindow
.GetSizePixel() );
345 Size
aOutputSize( aWindowSize
);
347 if( meAnimationMode
!= ANIMATIONMODE_SHOW
)
349 aOutputSize
.Width() = (long)( aOutputSize
.Width() / 1.03 );
350 aOutputSize
.Height() = (long)( aOutputSize
.Height() / 1.03 );
353 SdPage
* pP
= mpDoc
->GetSdPage( 0, PK_STANDARD
);
354 Size
aPageSize( pP
->GetSize() );
356 const double page_ratio
= (double)aPageSize
.Width() / (double)aPageSize
.Height();
357 const double output_ratio
= (double)aOutputSize
.Width() / (double)aOutputSize
.Height();
359 if( page_ratio
> output_ratio
)
361 aOutputSize
.Height() = ( aOutputSize
.Width() * aPageSize
.Height() ) / aPageSize
.Width();
363 else if( page_ratio
< output_ratio
)
365 aOutputSize
.Width() = ( aOutputSize
.Height() * aPageSize
.Width() ) / aPageSize
.Height();
368 Point
aOutputOffset( ( aWindowSize
.Width() - aOutputSize
.Width() ) >> 1,
369 ( aWindowSize
.Height() - aOutputSize
.Height() ) >> 1 );
371 // Reduce available width by one, as the slides might actually
372 // render one pixel wider and higher as aPageSize below specifies
373 // (when shapes of page size have visible border lines)
374 aOutputSize
.Width() --;
375 aOutputSize
.Height() --;
377 maPresentationArea
= Rectangle( aOutputOffset
, aOutputSize
);
378 mrOutputWindow
.SetPresentationArea( maPresentationArea
);
380 // scale presentation into available window rect (minus 10%); center in the window
381 const basegfx::B2DHomMatrix
aMatrix(basegfx::tools::createScaleTranslateB2DHomMatrix(
382 aOutputSize
.Width(), aOutputSize
.Height(), aOutputOffset
.X(), aOutputOffset
.Y()));
384 geometry::AffineMatrix2D aRes
;
386 return ::basegfx::unotools::affineMatrixFromHomMatrix( aRes
, aMatrix
);
389 void SAL_CALL
SlideShowView::addTransformationChangedListener( const Reference
< util::XModifyListener
>& xListener
) throw (RuntimeException
)
391 ::osl::MutexGuard
aGuard( m_aMutex
);
393 if( mpViewListeners
.get() )
394 mpViewListeners
->addListener( xListener
);
397 void SAL_CALL
SlideShowView::removeTransformationChangedListener( const Reference
< util::XModifyListener
>& xListener
) throw (RuntimeException
)
399 ::osl::MutexGuard
aGuard( m_aMutex
);
401 if( mpViewListeners
.get() )
402 mpViewListeners
->removeListener( xListener
);
405 void SAL_CALL
SlideShowView::addPaintListener( const Reference
< awt::XPaintListener
>& xListener
) throw (RuntimeException
)
407 ::osl::MutexGuard
aGuard( m_aMutex
);
409 if( mpPaintListeners
.get() )
410 mpPaintListeners
->addTypedListener( xListener
);
413 void SAL_CALL
SlideShowView::removePaintListener( const Reference
< awt::XPaintListener
>& xListener
) throw (RuntimeException
)
415 ::osl::MutexGuard
aGuard( m_aMutex
);
417 if( mpPaintListeners
.get() )
418 mpPaintListeners
->removeTypedListener( xListener
);
421 void SAL_CALL
SlideShowView::addMouseListener( const Reference
< awt::XMouseListener
>& xListener
) throw (RuntimeException
)
423 ::osl::MutexGuard
aGuard( m_aMutex
);
425 if( mpMouseListeners
.get() )
426 mpMouseListeners
->addTypedListener( xListener
);
429 void SAL_CALL
SlideShowView::removeMouseListener( const Reference
< awt::XMouseListener
>& xListener
) throw (RuntimeException
)
431 ::osl::MutexGuard
aGuard( m_aMutex
);
433 if( mpMouseListeners
.get() )
434 mpMouseListeners
->removeTypedListener( xListener
);
437 void SAL_CALL
SlideShowView::addMouseMotionListener( const Reference
< awt::XMouseMotionListener
>& xListener
) throw (RuntimeException
)
439 ::osl::MutexGuard
aGuard( m_aMutex
);
441 if( !mbIsMouseMotionListener
&& mxWindow
.is() )
443 // delay motion event registration, until we really
445 mbIsMouseMotionListener
= true;
446 mxWindow
->addMouseMotionListener( this );
449 if( mpMouseMotionListeners
.get() )
450 mpMouseMotionListeners
->addTypedListener( xListener
);
453 void SAL_CALL
SlideShowView::removeMouseMotionListener( const Reference
< awt::XMouseMotionListener
>& xListener
) throw (RuntimeException
)
455 ::osl::MutexGuard
aGuard( m_aMutex
);
457 if( mpMouseMotionListeners
.get() )
458 mpMouseMotionListeners
->removeTypedListener( xListener
);
460 // TODO(P1): Might be nice to deregister for mouse motion
461 // events, when the last listener is gone.
464 void SAL_CALL
SlideShowView::setMouseCursor( sal_Int16 nPointerShape
) throw (RuntimeException
)
466 ::osl::MutexGuard
aGuard( m_aMutex
);
470 mxPointer
->setType( nPointerShape
);
472 if( mxWindowPeer
.is() )
473 mxWindowPeer
->setPointer( mxPointer
);
476 awt::Rectangle SAL_CALL
SlideShowView::getCanvasArea( ) throw (RuntimeException
)
478 awt::Rectangle aRectangle
;
481 return mxWindow
->getPosSize();
483 aRectangle
.X
= aRectangle
.Y
= aRectangle
.Width
= aRectangle
.Height
= 0;
488 void SlideShowView::updateimpl( ::osl::ClearableMutexGuard
& rGuard
, SlideshowImpl
* pSlideShow
)
492 ::rtl::Reference
< SlideshowImpl
> aSLGuard( pSlideShow
);
496 mbFirstPaint
= false;
497 SlideshowImpl
* pTmpSlideShow
= mpSlideShow
;
500 pTmpSlideShow
->onFirstPaint();
504 pSlideShow
->startUpdateTimer();
508 // XWindowListener methods
509 void SAL_CALL
SlideShowView::windowResized( const awt::WindowEvent
& e
) throw (RuntimeException
)
511 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
513 if( mpViewListeners
.get() )
515 // Change event source, to enable listeners to match event
517 awt::WindowEvent
aEvent( e
);
518 aEvent
.Source
= static_cast< ::cppu::OWeakObject
* >( this );
520 mpViewListeners
->notify( aEvent
);
521 updateimpl( aGuard
, mpSlideShow
); // warning: clears guard!
525 void SAL_CALL
SlideShowView::windowMoved( const awt::WindowEvent
& ) throw (RuntimeException
)
530 void SAL_CALL
SlideShowView::windowShown( const lang::EventObject
& ) throw (RuntimeException
)
535 void SAL_CALL
SlideShowView::windowHidden( const lang::EventObject
& ) throw (RuntimeException
)
540 // XMouseListener implementation
541 void SAL_CALL
SlideShowView::mousePressed( const awt::MouseEvent
& e
) throw (uno::RuntimeException
)
543 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
544 if( mpSlideShow
&& mpSlideShow
->isInputFreezed() )
546 mbMousePressedEaten
= true;
550 mbMousePressedEaten
= false;
552 // Change event source, to enable listeners to match event
554 WrappedMouseEvent aEvent
;
555 aEvent
.meType
= WrappedMouseEvent::PRESSED
;
557 aEvent
.maEvent
.Source
= static_cast< ::cppu::OWeakObject
* >( this );
559 if( mpMouseListeners
.get() )
560 mpMouseListeners
->notify( aEvent
);
561 updateimpl( aGuard
, mpSlideShow
); // warning: clears guard!
565 void SAL_CALL
SlideShowView::mouseReleased( const awt::MouseEvent
& e
) throw (uno::RuntimeException
)
567 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
568 if( mbMousePressedEaten
)
570 // if mouse button down was ignored, also ignore mouse button up
571 mbMousePressedEaten
= false;
573 else if( mpSlideShow
&& !mpSlideShow
->isInputFreezed() )
575 // Change event source, to enable listeners to match event
577 WrappedMouseEvent aEvent
;
578 aEvent
.meType
= WrappedMouseEvent::RELEASED
;
580 aEvent
.maEvent
.Source
= static_cast< ::cppu::OWeakObject
* >( this );
582 if( mpMouseListeners
.get() )
583 mpMouseListeners
->notify( aEvent
);
584 updateimpl( aGuard
, mpSlideShow
); // warning: clears guard!
588 void SAL_CALL
SlideShowView::mouseEntered( const awt::MouseEvent
& e
) throw (uno::RuntimeException
)
590 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
592 // Change event source, to enable listeners to match event
594 WrappedMouseEvent aEvent
;
595 aEvent
.meType
= WrappedMouseEvent::ENTERED
;
597 aEvent
.maEvent
.Source
= static_cast< ::cppu::OWeakObject
* >( this );
599 if( mpMouseListeners
.get() )
600 mpMouseListeners
->notify( aEvent
);
601 updateimpl( aGuard
, mpSlideShow
); // warning: clears guard!
604 void SAL_CALL
SlideShowView::mouseExited( const awt::MouseEvent
& e
) throw (uno::RuntimeException
)
606 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
608 // Change event source, to enable listeners to match event
610 WrappedMouseEvent aEvent
;
611 aEvent
.meType
= WrappedMouseEvent::EXITED
;
613 aEvent
.maEvent
.Source
= static_cast< ::cppu::OWeakObject
* >( this );
615 if( mpMouseListeners
.get() )
616 mpMouseListeners
->notify( aEvent
);
617 updateimpl( aGuard
, mpSlideShow
); // warning: clears guard!
620 // XMouseMotionListener implementation
621 void SAL_CALL
SlideShowView::mouseDragged( const awt::MouseEvent
& e
) throw (uno::RuntimeException
)
623 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
625 // Change event source, to enable listeners to match event
627 WrappedMouseMotionEvent aEvent
;
628 aEvent
.meType
= WrappedMouseMotionEvent::DRAGGED
;
630 aEvent
.maEvent
.Source
= static_cast< ::cppu::OWeakObject
* >( this );
632 if( mpMouseMotionListeners
.get() )
633 mpMouseMotionListeners
->notify( aEvent
);
634 updateimpl( aGuard
, mpSlideShow
); // warning: clears guard!
637 void SAL_CALL
SlideShowView::mouseMoved( const awt::MouseEvent
& e
) throw (uno::RuntimeException
)
639 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
641 // Change event source, to enable listeners to match event
643 WrappedMouseMotionEvent aEvent
;
644 aEvent
.meType
= WrappedMouseMotionEvent::MOVED
;
646 aEvent
.maEvent
.Source
= static_cast< ::cppu::OWeakObject
* >( this );
648 if( mpMouseMotionListeners
.get() )
649 mpMouseMotionListeners
->notify( aEvent
);
650 updateimpl( aGuard
, mpSlideShow
); // warning: clears guard!
653 void SlideShowView::init()
655 mxWindow
->addWindowListener( this );
656 mxWindow
->addMouseListener( this );
658 mxPointer
= awt::Pointer::create( ::comphelper::getProcessComponentContext() );
662 // #i48939# only switch on kind of hacky scroll optimisation, when
663 // running fullscreen. this minimizes the probability that other
664 // windows partially cover the show.
669 Reference
< beans::XPropertySet
> xCanvasProps( getCanvas(),
670 uno::UNO_QUERY_THROW
);
671 xCanvasProps
->setPropertyValue("UnsafeScrolling",
672 uno::makeAny( true ) );
674 catch( uno::Exception
& )
682 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */