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>
34 using ::com::sun::star::uno::UNO_QUERY
;
35 using ::com::sun::star::uno::XInterface
;
36 using ::com::sun::star::uno::Reference
;
37 using ::com::sun::star::uno::WeakReference
;
38 using ::com::sun::star::uno::RuntimeException
;
39 using ::com::sun::star::lang::XComponent
;
40 using ::com::sun::star::uno::Exception
;
41 using ::com::sun::star::presentation::XSlideShow
;
42 using ::com::sun::star::presentation::XSlideShowView
;
43 using ::com::sun::star::presentation::XShapeEventListener
;
44 using ::com::sun::star::presentation::XSlideShowListener
;
46 using namespace ::com::sun::star
;
51 // SlideShowViewListeners
52 SlideShowViewListeners::SlideShowViewListeners( ::osl::Mutex
& rMutex
)
57 void SlideShowViewListeners::addListener( const Reference
< util::XModifyListener
>& _rxListener
)
59 ::osl::MutexGuard
aGuard( mrMutex
);
61 WeakReference
< util::XModifyListener
> xWeak( _rxListener
);
62 if( std::find( maListeners
.begin(), maListeners
.end(), xWeak
) == maListeners
.end() )
63 maListeners
.push_back( xWeak
);
66 void SlideShowViewListeners::removeListener( const Reference
< util::XModifyListener
>& _rxListener
)
68 ::osl::MutexGuard
aGuard( mrMutex
);
70 WeakReference
< util::XModifyListener
> xWeak( _rxListener
);
71 ViewListenerVector::iterator
aIter( std::find( maListeners
.begin(), maListeners
.end(), xWeak
) );
72 if( aIter
!= maListeners
.end() )
73 maListeners
.erase( aIter
);
76 bool SlideShowViewListeners::notify( const lang::EventObject
& _rEvent
) throw( com::sun::star::uno::Exception
)
78 ::osl::MutexGuard
aGuard( mrMutex
);
80 ViewListenerVector::iterator
aIter( maListeners
.begin() );
81 while( aIter
!= maListeners
.end() )
83 Reference
< util::XModifyListener
> xListener( (*aIter
) );
86 xListener
->modified( _rEvent
);
91 aIter
= maListeners
.erase( aIter
);
97 void SlideShowViewListeners::disposing( const lang::EventObject
& _rEventSource
)
99 ::osl::MutexGuard
aGuard( mrMutex
);
101 ViewListenerVector::iterator
aIter( maListeners
.begin() );
102 while( aIter
!= maListeners
.end() )
104 Reference
< util::XModifyListener
> xListener( (*aIter
++) );
106 xListener
->disposing( _rEventSource
);
112 // SlideShowViewPaintListeners
113 SlideShowViewPaintListeners::SlideShowViewPaintListeners( ::osl::Mutex
& rMutex
)
114 : SlideShowViewPaintListeners_Base( rMutex
)
118 bool SlideShowViewPaintListeners::implTypedNotify( const Reference
< awt::XPaintListener
>& rListener
,
119 const awt::PaintEvent
& rEvent
) throw( uno::Exception
)
121 rListener
->windowPaint( rEvent
);
122 return true; // continue calling listeners
125 // SlideShowViewMouseListeners
126 SlideShowViewMouseListeners::SlideShowViewMouseListeners( ::osl::Mutex
& rMutex
) :
127 SlideShowViewMouseListeners_Base( rMutex
)
131 bool SlideShowViewMouseListeners::implTypedNotify( const Reference
< awt::XMouseListener
>& rListener
,
132 const WrappedMouseEvent
& rEvent
) throw( uno::Exception
)
134 switch( rEvent
.meType
)
136 case WrappedMouseEvent::PRESSED
:
137 rListener
->mousePressed( rEvent
.maEvent
);
140 case WrappedMouseEvent::RELEASED
:
141 rListener
->mouseReleased( rEvent
.maEvent
);
144 case WrappedMouseEvent::ENTERED
:
145 rListener
->mouseEntered( rEvent
.maEvent
);
148 case WrappedMouseEvent::EXITED
:
149 rListener
->mouseExited( rEvent
.maEvent
);
153 return true; // continue calling listeners
156 // SlideShowViewMouseMotionListeners
157 SlideShowViewMouseMotionListeners::SlideShowViewMouseMotionListeners( ::osl::Mutex
& rMutex
) :
158 SlideShowViewMouseMotionListeners_Base( rMutex
)
162 bool SlideShowViewMouseMotionListeners::implTypedNotify( const Reference
< awt::XMouseMotionListener
>& rListener
,
163 const WrappedMouseMotionEvent
& rEvent
) throw( uno::Exception
)
165 switch( rEvent
.meType
)
167 case WrappedMouseMotionEvent::DRAGGED
:
168 rListener
->mouseDragged( rEvent
.maEvent
);
171 case WrappedMouseMotionEvent::MOVED
:
172 rListener
->mouseMoved( rEvent
.maEvent
);
176 return true; // continue calling listeners
180 SlideShowView::SlideShowView( ShowWindow
& rOutputWindow
,
181 SdDrawDocument
* pDoc
,
182 AnimationMode eAnimationMode
,
183 SlideshowImpl
* pSlideShow
,
185 : SlideShowView_Base( m_aMutex
),
186 mpCanvas( ::cppcanvas::VCLFactory::createSpriteCanvas( rOutputWindow
) ),
187 mxWindow( VCLUnoHelper::GetInterface( &rOutputWindow
), uno::UNO_QUERY_THROW
),
188 mxWindowPeer( mxWindow
, uno::UNO_QUERY_THROW
),
190 mpSlideShow( pSlideShow
),
191 mrOutputWindow( rOutputWindow
),
192 mpViewListeners( new SlideShowViewListeners( m_aMutex
) ),
193 mpPaintListeners( new SlideShowViewPaintListeners( m_aMutex
) ),
194 mpMouseListeners( new SlideShowViewMouseListeners( m_aMutex
) ),
195 mpMouseMotionListeners( new SlideShowViewMouseMotionListeners( m_aMutex
) ),
197 mbIsMouseMotionListener( false ),
198 meAnimationMode( eAnimationMode
),
199 mbFirstPaint( true ),
200 mbFullScreen( bFullScreen
),
201 mbMousePressedEaten( false )
205 mTranslationOffset
.Width
= 0;
206 mTranslationOffset
.Height
= 0;
209 // Dispose all internal references
210 void SAL_CALL
SlideShowView::dispose() throw (RuntimeException
, std::exception
)
212 ::osl::MutexGuard
aGuard( m_aMutex
);
216 // deregister listeners
219 mxWindow
->removeWindowListener( this );
220 mxWindow
->removeMouseListener( this );
222 if( mbIsMouseMotionListener
)
223 mxWindow
->removeMouseMotionListener( this );
229 // clear all listener containers
230 disposing( lang::EventObject() );
233 WeakComponentImplHelperBase::dispose();
236 // Disposing our broadcaster
237 void SAL_CALL
SlideShowView::disposing( const lang::EventObject
& ) throw(RuntimeException
, std::exception
)
239 ::osl::MutexGuard
aGuard( m_aMutex
);
241 // notify all listeners that _we_ are going down (send a disposing()),
242 // then delete listener containers:
243 lang::EventObject
const evt( static_cast<OWeakObject
*>(this) );
244 if (mpViewListeners
.get() != 0) {
245 mpViewListeners
->disposing( evt
);
246 mpViewListeners
.reset();
248 if (mpPaintListeners
.get() != 0) {
249 mpPaintListeners
->disposing( evt
);
250 mpPaintListeners
.reset();
252 if (mpMouseListeners
.get() != 0) {
253 mpMouseListeners
->disposing( evt
);
254 mpMouseListeners
.reset();
256 if (mpMouseMotionListeners
.get() != 0) {
257 mpMouseMotionListeners
->disposing( evt
);
258 mpMouseMotionListeners
.reset();
262 void SAL_CALL
SlideShowView::paint( const awt::PaintEvent
& e
) throw (RuntimeException
)
264 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
268 mbFirstPaint
= false;
269 SlideshowImpl
* pSlideShow
= mpSlideShow
;
272 pSlideShow
->onFirstPaint();
276 // Change event source, to enable listeners to match event
278 awt::PaintEvent
aEvent( e
);
279 aEvent
.Source
= static_cast< ::cppu::OWeakObject
* >( this );
280 mpPaintListeners
->notify( aEvent
);
281 updateimpl( aGuard
, mpSlideShow
); // warning: clears guard!
285 // XSlideShowView methods
286 Reference
< rendering::XSpriteCanvas
> SAL_CALL
SlideShowView::getCanvas( ) throw (RuntimeException
, std::exception
)
288 ::osl::MutexGuard
aGuard( m_aMutex
);
290 return mpCanvas
.get() ? mpCanvas
->getUNOSpriteCanvas() : Reference
< rendering::XSpriteCanvas
>();
293 void SAL_CALL
SlideShowView::clear() throw (::com::sun::star::uno::RuntimeException
, std::exception
)
295 // paint background in black
296 ::osl::MutexGuard
aGuard( m_aMutex
);
297 SolarMutexGuard aSolarGuard
;
299 // fill the bounds rectangle in black
301 const Size
aWindowSize( mrOutputWindow
.GetSizePixel() );
303 ::basegfx::B2DPolygon
aPoly( ::basegfx::tools::createPolygonFromRect(
304 ::basegfx::B2DRectangle(0.0,0.0,
306 aWindowSize
.Height() ) ) );
307 ::cppcanvas::PolyPolygonSharedPtr
pPolyPoly(
308 ::cppcanvas::BaseGfxFactory::createPolyPolygon( mpCanvas
, aPoly
) );
310 if( pPolyPoly
.get() )
312 pPolyPoly
->setRGBAFillColor( 0x000000FFU
);
317 geometry::IntegerSize2D SAL_CALL
SlideShowView::getTranslationOffset( ) throw (RuntimeException
, std::exception
)
319 return mTranslationOffset
;
322 geometry::AffineMatrix2D SAL_CALL
SlideShowView::getTransformation( ) throw (RuntimeException
, std::exception
)
324 ::osl::MutexGuard
aGuard( m_aMutex
);
325 SolarMutexGuard aSolarGuard
;
327 const Size
& rTmpSize( mrOutputWindow
.GetSizePixel() );
329 if (rTmpSize
.Width()<=0 || rTmpSize
.Height()<=0)
331 return geometry::AffineMatrix2D (1,0,0,0,1,0);
334 const Size
aWindowSize( mrOutputWindow
.GetSizePixel() );
335 Size
aOutputSize( aWindowSize
);
337 if( meAnimationMode
!= ANIMATIONMODE_SHOW
)
339 aOutputSize
.Width() = (long)( aOutputSize
.Width() / 1.03 );
340 aOutputSize
.Height() = (long)( aOutputSize
.Height() / 1.03 );
343 SdPage
* pP
= mpDoc
->GetSdPage( 0, PK_STANDARD
);
344 Size
aPageSize( pP
->GetSize() );
346 const double page_ratio
= (double)aPageSize
.Width() / (double)aPageSize
.Height();
347 const double output_ratio
= (double)aOutputSize
.Width() / (double)aOutputSize
.Height();
349 if( page_ratio
> output_ratio
)
351 aOutputSize
.Height() = ( aOutputSize
.Width() * aPageSize
.Height() ) / aPageSize
.Width();
353 else if( page_ratio
< output_ratio
)
355 aOutputSize
.Width() = ( aOutputSize
.Height() * aPageSize
.Width() ) / aPageSize
.Height();
358 Point
aOutputOffset( ( aWindowSize
.Width() - aOutputSize
.Width() ) >> 1,
359 ( aWindowSize
.Height() - aOutputSize
.Height() ) >> 1 );
361 // Reduce available width by one, as the slides might actually
362 // render one pixel wider and higher as aPageSize below specifies
363 // (when shapes of page size have visible border lines)
364 aOutputSize
.Width() --;
365 aOutputSize
.Height() --;
367 // Record mTranslationOffset
368 mTranslationOffset
.Height
= aOutputOffset
.Y();
369 mTranslationOffset
.Width
= aOutputOffset
.X();
371 maPresentationArea
= Rectangle( aOutputOffset
, aOutputSize
);
372 mrOutputWindow
.SetPresentationArea( maPresentationArea
);
374 // scale presentation into available window rect (minus 10%); center in the window
375 const basegfx::B2DHomMatrix
aMatrix(basegfx::tools::createScaleTranslateB2DHomMatrix(
376 aOutputSize
.Width(), aOutputSize
.Height(), aOutputOffset
.X(), aOutputOffset
.Y()));
378 geometry::AffineMatrix2D aRes
;
380 return ::basegfx::unotools::affineMatrixFromHomMatrix( aRes
, aMatrix
);
383 void SAL_CALL
SlideShowView::addTransformationChangedListener( const Reference
< util::XModifyListener
>& xListener
) throw (RuntimeException
, std::exception
)
385 ::osl::MutexGuard
aGuard( m_aMutex
);
387 if( mpViewListeners
.get() )
388 mpViewListeners
->addListener( xListener
);
391 void SAL_CALL
SlideShowView::removeTransformationChangedListener( const Reference
< util::XModifyListener
>& xListener
) throw (RuntimeException
, std::exception
)
393 ::osl::MutexGuard
aGuard( m_aMutex
);
395 if( mpViewListeners
.get() )
396 mpViewListeners
->removeListener( xListener
);
399 void SAL_CALL
SlideShowView::addPaintListener( const Reference
< awt::XPaintListener
>& xListener
) throw (RuntimeException
, std::exception
)
401 ::osl::MutexGuard
aGuard( m_aMutex
);
403 if( mpPaintListeners
.get() )
404 mpPaintListeners
->addTypedListener( xListener
);
407 void SAL_CALL
SlideShowView::removePaintListener( const Reference
< awt::XPaintListener
>& xListener
) throw (RuntimeException
, std::exception
)
409 ::osl::MutexGuard
aGuard( m_aMutex
);
411 if( mpPaintListeners
.get() )
412 mpPaintListeners
->removeTypedListener( xListener
);
415 void SAL_CALL
SlideShowView::addMouseListener( const Reference
< awt::XMouseListener
>& xListener
) throw (RuntimeException
, std::exception
)
417 ::osl::MutexGuard
aGuard( m_aMutex
);
419 if( mpMouseListeners
.get() )
420 mpMouseListeners
->addTypedListener( xListener
);
423 void SAL_CALL
SlideShowView::removeMouseListener( const Reference
< awt::XMouseListener
>& xListener
) throw (RuntimeException
, std::exception
)
425 ::osl::MutexGuard
aGuard( m_aMutex
);
427 if( mpMouseListeners
.get() )
428 mpMouseListeners
->removeTypedListener( xListener
);
431 void SAL_CALL
SlideShowView::addMouseMotionListener( const Reference
< awt::XMouseMotionListener
>& xListener
) throw (RuntimeException
, std::exception
)
433 ::osl::MutexGuard
aGuard( m_aMutex
);
435 if( !mbIsMouseMotionListener
&& mxWindow
.is() )
437 // delay motion event registration, until we really
439 mbIsMouseMotionListener
= true;
440 mxWindow
->addMouseMotionListener( this );
443 if( mpMouseMotionListeners
.get() )
444 mpMouseMotionListeners
->addTypedListener( xListener
);
447 void SAL_CALL
SlideShowView::removeMouseMotionListener( const Reference
< awt::XMouseMotionListener
>& xListener
) throw (RuntimeException
, std::exception
)
449 ::osl::MutexGuard
aGuard( m_aMutex
);
451 if( mpMouseMotionListeners
.get() )
452 mpMouseMotionListeners
->removeTypedListener( xListener
);
454 // TODO(P1): Might be nice to deregister for mouse motion
455 // events, when the last listener is gone.
458 void SAL_CALL
SlideShowView::setMouseCursor( sal_Int16 nPointerShape
) throw (RuntimeException
, std::exception
)
460 ::osl::MutexGuard
aGuard( m_aMutex
);
464 mxPointer
->setType( nPointerShape
);
466 if( mxWindowPeer
.is() )
467 mxWindowPeer
->setPointer( mxPointer
);
470 awt::Rectangle SAL_CALL
SlideShowView::getCanvasArea( ) throw (RuntimeException
, std::exception
)
472 awt::Rectangle aRectangle
;
475 return mxWindow
->getPosSize();
477 aRectangle
.X
= aRectangle
.Y
= aRectangle
.Width
= aRectangle
.Height
= 0;
482 void SlideShowView::updateimpl( ::osl::ClearableMutexGuard
& rGuard
, SlideshowImpl
* pSlideShow
)
486 ::rtl::Reference
< SlideshowImpl
> aSLGuard( pSlideShow
);
490 mbFirstPaint
= false;
491 SlideshowImpl
* pTmpSlideShow
= mpSlideShow
;
494 pTmpSlideShow
->onFirstPaint();
498 pSlideShow
->startUpdateTimer();
502 // XWindowListener methods
503 void SAL_CALL
SlideShowView::windowResized( const awt::WindowEvent
& e
) throw (RuntimeException
, std::exception
)
505 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
507 if( mpViewListeners
.get() )
509 // Change event source, to enable listeners to match event
511 awt::WindowEvent
aEvent( e
);
512 aEvent
.Source
= static_cast< ::cppu::OWeakObject
* >( this );
514 mpViewListeners
->notify( aEvent
);
515 updateimpl( aGuard
, mpSlideShow
); // warning: clears guard!
519 void SAL_CALL
SlideShowView::windowMoved( const awt::WindowEvent
& ) throw (RuntimeException
, std::exception
)
524 void SAL_CALL
SlideShowView::windowShown( const lang::EventObject
& ) throw (RuntimeException
, std::exception
)
529 void SAL_CALL
SlideShowView::windowHidden( const lang::EventObject
& ) throw (RuntimeException
, std::exception
)
534 // XMouseListener implementation
535 void SAL_CALL
SlideShowView::mousePressed( const awt::MouseEvent
& e
) throw (uno::RuntimeException
, std::exception
)
537 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
538 if( mpSlideShow
&& mpSlideShow
->isInputFreezed() )
540 mbMousePressedEaten
= true;
544 mbMousePressedEaten
= false;
546 // Change event source, to enable listeners to match event
548 WrappedMouseEvent aEvent
;
549 aEvent
.meType
= WrappedMouseEvent::PRESSED
;
551 aEvent
.maEvent
.Source
= static_cast< ::cppu::OWeakObject
* >( this );
553 if( mpMouseListeners
.get() )
554 mpMouseListeners
->notify( aEvent
);
555 updateimpl( aGuard
, mpSlideShow
); // warning: clears guard!
559 void SAL_CALL
SlideShowView::mouseReleased( const awt::MouseEvent
& e
) throw (uno::RuntimeException
, std::exception
)
561 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
562 if( mbMousePressedEaten
)
564 // if mouse button down was ignored, also ignore mouse button up
565 mbMousePressedEaten
= false;
567 else if( mpSlideShow
&& !mpSlideShow
->isInputFreezed() )
569 // Change event source, to enable listeners to match event
571 WrappedMouseEvent aEvent
;
572 aEvent
.meType
= WrappedMouseEvent::RELEASED
;
574 aEvent
.maEvent
.Source
= static_cast< ::cppu::OWeakObject
* >( this );
576 if( mpMouseListeners
.get() )
577 mpMouseListeners
->notify( aEvent
);
578 updateimpl( aGuard
, mpSlideShow
); // warning: clears guard!
582 void SAL_CALL
SlideShowView::mouseEntered( const awt::MouseEvent
& e
) throw (uno::RuntimeException
, std::exception
)
584 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
586 // Change event source, to enable listeners to match event
588 WrappedMouseEvent aEvent
;
589 aEvent
.meType
= WrappedMouseEvent::ENTERED
;
591 aEvent
.maEvent
.Source
= static_cast< ::cppu::OWeakObject
* >( this );
593 if( mpMouseListeners
.get() )
594 mpMouseListeners
->notify( aEvent
);
595 updateimpl( aGuard
, mpSlideShow
); // warning: clears guard!
598 void SAL_CALL
SlideShowView::mouseExited( const awt::MouseEvent
& e
) throw (uno::RuntimeException
, std::exception
)
600 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
602 // Change event source, to enable listeners to match event
604 WrappedMouseEvent aEvent
;
605 aEvent
.meType
= WrappedMouseEvent::EXITED
;
607 aEvent
.maEvent
.Source
= static_cast< ::cppu::OWeakObject
* >( this );
609 if( mpMouseListeners
.get() )
610 mpMouseListeners
->notify( aEvent
);
611 updateimpl( aGuard
, mpSlideShow
); // warning: clears guard!
614 // XMouseMotionListener implementation
615 void SAL_CALL
SlideShowView::mouseDragged( const awt::MouseEvent
& e
) throw (uno::RuntimeException
, std::exception
)
617 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
619 // Change event source, to enable listeners to match event
621 WrappedMouseMotionEvent aEvent
;
622 aEvent
.meType
= WrappedMouseMotionEvent::DRAGGED
;
624 aEvent
.maEvent
.Source
= static_cast< ::cppu::OWeakObject
* >( this );
626 if( mpMouseMotionListeners
.get() )
627 mpMouseMotionListeners
->notify( aEvent
);
628 updateimpl( aGuard
, mpSlideShow
); // warning: clears guard!
631 void SAL_CALL
SlideShowView::mouseMoved( const awt::MouseEvent
& e
) throw (uno::RuntimeException
, std::exception
)
633 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
635 // Change event source, to enable listeners to match event
637 WrappedMouseMotionEvent aEvent
;
638 aEvent
.meType
= WrappedMouseMotionEvent::MOVED
;
640 aEvent
.maEvent
.Source
= static_cast< ::cppu::OWeakObject
* >( this );
642 if( mpMouseMotionListeners
.get() )
643 mpMouseMotionListeners
->notify( aEvent
);
644 updateimpl( aGuard
, mpSlideShow
); // warning: clears guard!
647 void SlideShowView::init()
649 mxWindow
->addWindowListener( this );
650 mxWindow
->addMouseListener( this );
652 mxPointer
= awt::Pointer::create( ::comphelper::getProcessComponentContext() );
656 // #i48939# only switch on kind of hacky scroll optimization, when
657 // running fullscreen. this minimizes the probability that other
658 // windows partially cover the show.
663 Reference
< beans::XPropertySet
> xCanvasProps( getCanvas(),
664 uno::UNO_QUERY_THROW
);
665 xCanvasProps
->setPropertyValue("UnsafeScrolling",
666 uno::makeAny( true ) );
668 catch( uno::Exception
& )
676 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */