1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <sal/config.h>
21 
22 #include <algorithm>
23 
24 #include <config_features.h>
25 
26 #include <com/sun/star/frame/theAutoRecovery.hpp>
27 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
28 #include <com/sun/star/document/XEventsSupplier.hpp>
29 #include <com/sun/star/drawing/XMasterPageTarget.hpp>
30 #include <com/sun/star/beans/PropertyValue.hpp>
31 #include <com/sun/star/beans/XPropertySetInfo.hpp>
32 #include <com/sun/star/beans/XPropertySet.hpp>
33 #include <com/sun/star/awt/SystemPointer.hpp>
34 #include <com/sun/star/util/URLTransformer.hpp>
35 #include <com/sun/star/util/XURLTransformer.hpp>
36 #include <com/sun/star/frame/XDispatch.hpp>
37 #include <com/sun/star/frame/XLayoutManager.hpp>
38 #include <com/sun/star/presentation/SlideShow.hpp>
39 #include <com/sun/star/media/XPlayer.hpp>
40 #include <svl/stritem.hxx>
41 #include <svl/urihelper.hxx>
42 #include <unotools/saveopt.hxx>
43 #include <basic/sbstar.hxx>
44 
45 #include <toolkit/helper/vclunohelper.hxx>
46 #include <tools/diagnose_ex.h>
47 
48 #include <sfx2/infobar.hxx>
49 #include <sfx2/dispatch.hxx>
50 #include <sfx2/docfile.hxx>
51 #include <sfx2/app.hxx>
52 #include <sfx2/viewfrm.hxx>
53 #include <svx/unoapi.hxx>
54 #include <svx/svdoole2.hxx>
55 #include <svx/f3dchild.hxx>
56 #include <svx/imapdlg.hxx>
57 #include <svx/fontwork.hxx>
58 #include <svx/SvxColorChildWindow.hxx>
59 #include <svx/bmpmask.hxx>
60 #include <svx/srchdlg.hxx>
61 #include <svx/hyperdlg.hxx>
62 #include <svx/svxids.hrc>
63 #include <AnimationChildWindow.hxx>
64 #include <notifydocumentevent.hxx>
65 #include "slideshowimpl.hxx"
66 #include "slideshowviewimpl.hxx"
67 #include "PaneHider.hxx"
68 
69 #include <bitmaps.hlst>
70 #include <strings.hrc>
71 #include <sdresid.hxx>
72 #include <vcl/canvastools.hxx>
73 #include <vcl/commandevent.hxx>
74 #include <vcl/commandinfoprovider.hxx>
75 #include <vcl/weldutils.hxx>
76 
77 #include <vcl/settings.hxx>
78 #include <vcl/scheduler.hxx>
79 #include <vcl/svapp.hxx>
80 #include <vcl/help.hxx>
81 #include <comphelper/processfactory.hxx>
82 #include <rtl/ref.hxx>
83 #include <avmedia/mediawindow.hxx>
84 #include <svtools/colrdlg.hxx>
85 #include <DrawDocShell.hxx>
86 #include <ViewShellBase.hxx>
87 #include <PresentationViewShell.hxx>
88 #include <RemoteServer.hxx>
89 #include <customshowlist.hxx>
90 #include <unopage.hxx>
91 #include <sdpage.hxx>
92 #include <sdmod.hxx>
93 #include <app.hrc>
94 #include <cusshow.hxx>
95 #include <optsitem.hxx>
96 
97 #define CM_SLIDES       21
98 
99 using ::com::sun::star::animations::XAnimationNode;
100 using ::com::sun::star::animations::XAnimationListener;
101 using ::com::sun::star::awt::XWindow;
102 using namespace ::com::sun::star;
103 using namespace ::com::sun::star::lang;
104 using namespace ::com::sun::star::uno;
105 using namespace ::com::sun::star::drawing;
106 using namespace ::com::sun::star::container;
107 using namespace ::com::sun::star::document;
108 using namespace ::com::sun::star::presentation;
109 using namespace ::com::sun::star::beans;
110 
111 namespace sd
112 {
113 /** Slots, which will be disabled in the slide show and are managed by Sfx.
114     Have to be sorted in the order of the SIDs */
115 sal_uInt16 const pAllowed[] =
116 {
117     SID_OPENDOC                             , //     5501   ///< that internally jumps work
118     SID_JUMPTOMARK                          , //     5598
119     SID_OPENHYPERLINK                       , //     6676
120     SID_PRESENTATION_END                     //    27218
121 };
122 
123 class AnimationSlideController
124 {
125 public:
126     enum Mode { ALL, FROM, CUSTOM, PREVIEW };
127 
128 public:
129     AnimationSlideController( Reference< XIndexAccess > const & xSlides, Mode eMode );
130 
setStartSlideNumber(sal_Int32 nSlideNumber)131     void setStartSlideNumber( sal_Int32 nSlideNumber ) { mnStartSlideNumber = nSlideNumber; }
132     sal_Int32 getStartSlideIndex() const;
133 
134     sal_Int32 getCurrentSlideNumber() const;
135     sal_Int32 getCurrentSlideIndex() const;
136 
getSlideIndexCount() const137     sal_Int32 getSlideIndexCount() const { return maSlideNumbers.size(); }
getSlideNumberCount() const138     sal_Int32 getSlideNumberCount() const { return mnSlideCount; }
139 
140     sal_Int32 getSlideNumber( sal_Int32 nSlideIndex ) const;
141 
142     void insertSlideNumber( sal_Int32 nSlideNumber, bool bVisible = true );
143     void setPreviewNode( const Reference< XAnimationNode >& xPreviewNode );
144 
145     bool jumpToSlideIndex( sal_Int32 nNewSlideIndex );
146     bool jumpToSlideNumber( sal_Int32 nNewSlideIndex );
147 
148     bool nextSlide();
149     bool previousSlide();
150 
151     void displayCurrentSlide( const Reference< XSlideShow >& xShow,
152                               const Reference< XDrawPagesSupplier>& xDrawPages,
153                               const bool bSkipAllMainSequenceEffects );
154 
155     sal_Int32 getNextSlideIndex() const;
156     sal_Int32 getPreviousSlideIndex() const;
157 
158     bool isVisibleSlideNumber( sal_Int32 nSlideNumber ) const;
159 
160     Reference< XDrawPage > getSlideByNumber( sal_Int32 nSlideNumber ) const;
161 
162     sal_Int32 getNextSlideNumber() const;
163 
hasSlides() const164     bool hasSlides() const { return !maSlideNumbers.empty(); }
165 
166 private:
167     bool getSlideAPI( sal_Int32 nSlideNumber, Reference< XDrawPage >& xSlide, Reference< XAnimationNode >& xAnimNode );
168     sal_Int32 findSlideIndex( sal_Int32 nSlideNumber ) const;
169 
isValidIndex(sal_Int32 nIndex) const170     bool isValidIndex( sal_Int32 nIndex ) const { return (nIndex >= 0) && (nIndex < static_cast<sal_Int32>(maSlideNumbers.size())); }
isValidSlideNumber(sal_Int32 nSlideNumber) const171     bool isValidSlideNumber( sal_Int32 nSlideNumber ) const { return (nSlideNumber >= 0) && (nSlideNumber < mnSlideCount); }
172 
173 private:
174     Mode meMode;
175     sal_Int32 mnStartSlideNumber;
176     std::vector< sal_Int32 > maSlideNumbers;
177     std::vector< bool > maSlideVisible;
178     std::vector< bool > maSlideVisited;
179     Reference< XAnimationNode > mxPreviewNode;
180     sal_Int32 mnSlideCount;
181     sal_Int32 mnCurrentSlideIndex;
182     sal_Int32 mnHiddenSlideNumber;
183     Reference< XIndexAccess > mxSlides;
184 };
185 
getSlideByNumber(sal_Int32 nSlideNumber) const186 Reference< XDrawPage > AnimationSlideController::getSlideByNumber( sal_Int32 nSlideNumber ) const
187 {
188     Reference< XDrawPage > xSlide;
189     if( mxSlides.is() && (nSlideNumber >= 0) && (nSlideNumber < mxSlides->getCount()) )
190         mxSlides->getByIndex( nSlideNumber ) >>= xSlide;
191     return xSlide;
192 }
193 
isVisibleSlideNumber(sal_Int32 nSlideNumber) const194 bool AnimationSlideController::isVisibleSlideNumber( sal_Int32 nSlideNumber ) const
195 {
196     sal_Int32 nIndex = findSlideIndex( nSlideNumber );
197 
198     if( nIndex != -1 )
199         return maSlideVisible[ nIndex ];
200     else
201         return false;
202 }
203 
setPreviewNode(const Reference<XAnimationNode> & xPreviewNode)204 void AnimationSlideController::setPreviewNode( const Reference< XAnimationNode >& xPreviewNode )
205 {
206     mxPreviewNode = xPreviewNode;
207 }
208 
AnimationSlideController(Reference<XIndexAccess> const & xSlides,Mode eMode)209 AnimationSlideController::AnimationSlideController( Reference< XIndexAccess > const & xSlides, Mode eMode  )
210 :   meMode( eMode )
211 ,   mnStartSlideNumber(-1)
212 ,   mnSlideCount( 0 )
213 ,   mnCurrentSlideIndex(0)
214 ,   mnHiddenSlideNumber( -1 )
215 ,   mxSlides( xSlides )
216 {
217     if( mxSlides.is() )
218         mnSlideCount = xSlides->getCount();
219 }
220 
getStartSlideIndex() const221 sal_Int32 AnimationSlideController::getStartSlideIndex() const
222 {
223     if( mnStartSlideNumber >= 0 )
224     {
225         sal_Int32 nIndex;
226         const sal_Int32 nCount = maSlideNumbers.size();
227 
228         for( nIndex = 0; nIndex < nCount; nIndex++ )
229         {
230             if( maSlideNumbers[nIndex] == mnStartSlideNumber )
231                 return nIndex;
232         }
233     }
234 
235     return 0;
236 }
237 
getCurrentSlideNumber() const238 sal_Int32 AnimationSlideController::getCurrentSlideNumber() const
239 {
240     if( mnHiddenSlideNumber != -1 )
241         return mnHiddenSlideNumber;
242     else if( !maSlideNumbers.empty() )
243         return maSlideNumbers[mnCurrentSlideIndex];
244     else
245         return 0;
246 }
247 
getCurrentSlideIndex() const248 sal_Int32 AnimationSlideController::getCurrentSlideIndex() const
249 {
250     if( mnHiddenSlideNumber != -1 )
251         return -1;
252     else
253         return mnCurrentSlideIndex;
254 }
255 
jumpToSlideIndex(sal_Int32 nNewSlideIndex)256 bool AnimationSlideController::jumpToSlideIndex( sal_Int32 nNewSlideIndex )
257 {
258     if( isValidIndex( nNewSlideIndex ) )
259     {
260         mnCurrentSlideIndex = nNewSlideIndex;
261         mnHiddenSlideNumber = -1;
262         maSlideVisited[mnCurrentSlideIndex] = true;
263         return true;
264     }
265     else
266     {
267         return false;
268     }
269 }
270 
jumpToSlideNumber(sal_Int32 nNewSlideNumber)271 bool AnimationSlideController::jumpToSlideNumber( sal_Int32 nNewSlideNumber )
272 {
273     sal_Int32 nIndex = findSlideIndex( nNewSlideNumber );
274     if( isValidIndex( nIndex ) )
275     {
276         return jumpToSlideIndex( nIndex );
277     }
278     else if( (nNewSlideNumber >= 0) && (nNewSlideNumber < mnSlideCount) )
279     {
280         // jump to a hidden slide
281         mnHiddenSlideNumber = nNewSlideNumber;
282         return true;
283     }
284     else
285     {
286         return false;
287     }
288 }
289 
getSlideNumber(sal_Int32 nSlideIndex) const290 sal_Int32 AnimationSlideController::getSlideNumber( sal_Int32 nSlideIndex ) const
291 {
292     if( isValidIndex( nSlideIndex ) )
293         return maSlideNumbers[nSlideIndex];
294     else
295         return -1;
296 }
297 
insertSlideNumber(sal_Int32 nSlideNumber,bool bVisible)298 void AnimationSlideController::insertSlideNumber( sal_Int32 nSlideNumber, bool bVisible /* = true */ )
299 {
300     DBG_ASSERT( isValidSlideNumber( nSlideNumber ), "sd::AnimationSlideController::insertSlideNumber(), illegal index" );
301     if( isValidSlideNumber( nSlideNumber ) )
302     {
303         maSlideNumbers.push_back( nSlideNumber );
304         maSlideVisible.push_back( bVisible );
305         maSlideVisited.push_back( false );
306     }
307 }
308 
getSlideAPI(sal_Int32 nSlideNumber,Reference<XDrawPage> & xSlide,Reference<XAnimationNode> & xAnimNode)309 bool AnimationSlideController::getSlideAPI( sal_Int32 nSlideNumber, Reference< XDrawPage >& xSlide, Reference< XAnimationNode >& xAnimNode )
310 {
311     if( isValidSlideNumber( nSlideNumber ) ) try
312     {
313         xSlide.set( mxSlides->getByIndex(nSlideNumber), UNO_QUERY_THROW );
314 
315         if( meMode == PREVIEW )
316         {
317             xAnimNode = mxPreviewNode;
318         }
319         else
320         {
321             Reference< animations::XAnimationNodeSupplier > xAnimNodeSupplier( xSlide, UNO_QUERY_THROW );
322             xAnimNode = xAnimNodeSupplier->getAnimationNode();
323         }
324 
325         return true;
326     }
327     catch( Exception& )
328     {
329         TOOLS_WARN_EXCEPTION( "sd", "sd::AnimationSlideController::getSlideAPI()" );
330     }
331 
332     return false;
333 }
334 
findSlideIndex(sal_Int32 nSlideNumber) const335 sal_Int32 AnimationSlideController::findSlideIndex( sal_Int32 nSlideNumber ) const
336 {
337     sal_Int32 nIndex;
338     const sal_Int32 nCount = maSlideNumbers.size();
339 
340     for( nIndex = 0; nIndex < nCount; nIndex++ )
341     {
342         if( maSlideNumbers[nIndex] == nSlideNumber )
343             return nIndex;
344     }
345 
346     return -1;
347 }
348 
getNextSlideIndex() const349 sal_Int32 AnimationSlideController::getNextSlideIndex() const
350 {
351     switch( meMode )
352     {
353     case ALL:
354         {
355             sal_Int32 nNewSlideIndex = mnCurrentSlideIndex + 1;
356             if( isValidIndex( nNewSlideIndex ) )
357             {
358                 // if the current slide is not excluded, make sure the
359                 // next slide is also not excluded.
360                 // if the current slide is excluded, we want to go
361                 // to the next slide, even if this is also excluded.
362                 if( maSlideVisible[mnCurrentSlideIndex] )
363                 {
364                     while( isValidIndex( nNewSlideIndex ) )
365                     {
366                         if( maSlideVisible[nNewSlideIndex] )
367                             break;
368 
369                         nNewSlideIndex++;
370                     }
371                 }
372             }
373             return isValidIndex( nNewSlideIndex ) ? nNewSlideIndex : -1;
374         }
375 
376     case FROM:
377     case CUSTOM:
378         return mnHiddenSlideNumber == -1 ? mnCurrentSlideIndex + 1 : mnCurrentSlideIndex;
379 
380     default:
381     case PREVIEW:
382         return -1;
383 
384     }
385 }
386 
getNextSlideNumber() const387 sal_Int32 AnimationSlideController::getNextSlideNumber() const
388 {
389     sal_Int32 nNextSlideIndex = getNextSlideIndex();
390     if( isValidIndex( nNextSlideIndex ) )
391     {
392         return maSlideNumbers[nNextSlideIndex];
393     }
394     else
395     {
396         return -1;
397     }
398 }
399 
nextSlide()400 bool AnimationSlideController::nextSlide()
401 {
402     return jumpToSlideIndex( getNextSlideIndex() );
403 }
404 
getPreviousSlideIndex() const405 sal_Int32 AnimationSlideController::getPreviousSlideIndex() const
406 {
407     sal_Int32 nNewSlideIndex = mnCurrentSlideIndex - 1;
408 
409     switch( meMode )
410     {
411         case ALL:
412         {
413             // make sure the previous slide is visible
414             // or was already visited
415             while( isValidIndex( nNewSlideIndex ) )
416             {
417                 if( maSlideVisible[nNewSlideIndex] || maSlideVisited[nNewSlideIndex] )
418                     break;
419 
420                 nNewSlideIndex--;
421             }
422 
423             break;
424         }
425 
426         case PREVIEW:
427             return -1;
428 
429         default:
430             break;
431     }
432 
433     return nNewSlideIndex;
434 }
435 
previousSlide()436 bool AnimationSlideController::previousSlide()
437 {
438     return jumpToSlideIndex( getPreviousSlideIndex() );
439 }
440 
displayCurrentSlide(const Reference<XSlideShow> & xShow,const Reference<XDrawPagesSupplier> & xDrawPages,const bool bSkipAllMainSequenceEffects)441 void AnimationSlideController::displayCurrentSlide( const Reference< XSlideShow >& xShow,
442                                                     const Reference< XDrawPagesSupplier>& xDrawPages,
443                                                     const bool bSkipAllMainSequenceEffects )
444 {
445     const sal_Int32 nCurrentSlideNumber = getCurrentSlideNumber();
446 
447     if( !(xShow.is() && (nCurrentSlideNumber != -1 )) )
448         return;
449 
450     Reference< XDrawPage > xSlide;
451     Reference< XAnimationNode > xAnimNode;
452     ::std::vector<PropertyValue> aProperties;
453 
454     const sal_Int32 nNextSlideNumber = getNextSlideNumber();
455     if( getSlideAPI( nNextSlideNumber, xSlide, xAnimNode )  )
456     {
457         Sequence< Any > aValue(2);
458         aValue[0] <<= xSlide;
459         aValue[1] <<= xAnimNode;
460         aProperties.emplace_back( "Prefetch" ,
461                 -1,
462                 Any(aValue),
463                 PropertyState_DIRECT_VALUE);
464     }
465     if (bSkipAllMainSequenceEffects)
466     {
467         // Add one property that prevents the slide transition from being
468         // shown (to speed up the transition to the previous slide) and
469         // one to show all main sequence effects so that the user can
470         // continue to undo effects.
471         aProperties.emplace_back( "SkipAllMainSequenceEffects",
472                 -1,
473                 Any(true),
474                 PropertyState_DIRECT_VALUE);
475         aProperties.emplace_back("SkipSlideTransition",
476                 -1,
477                 Any(true),
478                 PropertyState_DIRECT_VALUE);
479     }
480 
481     if( getSlideAPI( nCurrentSlideNumber, xSlide, xAnimNode ) )
482         xShow->displaySlide( xSlide, xDrawPages, xAnimNode, comphelper::containerToSequence(aProperties) );
483 }
484 
485 constexpr OUStringLiteral gsOnClick( u"OnClick" );
486 constexpr OUStringLiteral gsBookmark( u"Bookmark" );
487 constexpr OUStringLiteral gsVerb( u"Verb" );
488 
SlideshowImpl(const Reference<XPresentation2> & xPresentation,ViewShell * pViewSh,::sd::View * pView,SdDrawDocument * pDoc,vcl::Window * pParentWindow)489 SlideshowImpl::SlideshowImpl( const Reference< XPresentation2 >& xPresentation, ViewShell* pViewSh, ::sd::View* pView, SdDrawDocument* pDoc, vcl::Window* pParentWindow )
490 : SlideshowImplBase( m_aMutex )
491 , mxModel(pDoc->getUnoModel(),UNO_QUERY_THROW)
492 , mpView(pView)
493 , mpViewShell(pViewSh)
494 , mpDocSh(pDoc->GetDocSh())
495 , mpDoc(pDoc)
496 , mpParentWindow(pParentWindow)
497 , mpShowWindow(nullptr)
498 , mnRestoreSlide(0)
499 , maPresSize( -1, -1 )
500 , meAnimationMode(ANIMATIONMODE_SHOW)
501 , mpOldActiveWindow(nullptr)
502 , mnChildMask( 0 )
503 , mbDisposed(false)
504 , mbAutoSaveWasOn(false)
505 , mbRehearseTimings(false)
506 , mbIsPaused(false)
507 , mbWasPaused(false)
508 , mbInputFreeze(false)
509 , mbActive(false)
510 , maPresSettings( pDoc->getPresentationSettings() )
511 , mnUserPaintColor( 0x80ff0000L )
512 , mbUsePen(false)
513 , mdUserPaintStrokeWidth ( 150.0 )
514 , mnEndShowEvent(nullptr)
515 , mnContextMenuEvent(nullptr)
516 , mxPresentation( xPresentation )
517 {
518     if( mpViewShell )
519         mpOldActiveWindow = mpViewShell->GetActiveWindow();
520 
521     maUpdateTimer.SetDebugName("SlideShowImpl maUpdateTimer");
522     maUpdateTimer.SetInvokeHandler(LINK(this, SlideshowImpl, updateHdl));
523     // Priority must not be too high or we'll starve input handling etc.
524     maUpdateTimer.SetPriority(TaskPriority::REPAINT);
525 
526     maDeactivateTimer.SetDebugName("SlideShowImpl maDeactivateTimer");
527     maDeactivateTimer.SetInvokeHandler(LINK(this, SlideshowImpl, deactivateHdl));
528     maDeactivateTimer.SetTimeout( 20 );
529 
530     maInputFreezeTimer.SetDebugName("SlideShowImpl maInputFreezeTimer");
531     maInputFreezeTimer.SetInvokeHandler( LINK( this, SlideshowImpl, ReadyForNextInputHdl ) );
532     maInputFreezeTimer.SetTimeout( 20 );
533 
534     SvtSaveOptions aOptions;
535 
536         // no autosave during show
537     if( aOptions.IsAutoSave() )
538         mbAutoSaveWasOn = true;
539 
540     Application::AddEventListener( LINK( this, SlideshowImpl, EventListenerHdl ) );
541 
542     mbUsePen = maPresSettings.mbMouseAsPen;
543 
544     SdOptions* pOptions = SD_MOD()->GetSdOptions(DocumentType::Impress);
545     if( pOptions )
546     {
547         mnUserPaintColor = pOptions->GetPresentationPenColor();
548         mdUserPaintStrokeWidth = pOptions->GetPresentationPenWidth();
549     }
550 }
551 
~SlideshowImpl()552 SlideshowImpl::~SlideshowImpl()
553 {
554     SdModule *pModule = SD_MOD();
555     //rhbz#806663 SlideshowImpl can outlive SdModule
556     SdOptions* pOptions = pModule ?
557         pModule->GetSdOptions(DocumentType::Impress) : nullptr;
558     if( pOptions )
559     {
560         pOptions->SetPresentationPenColor(mnUserPaintColor);
561         pOptions->SetPresentationPenWidth(mdUserPaintStrokeWidth);
562     }
563 
564     Application::RemoveEventListener( LINK( this, SlideshowImpl, EventListenerHdl ) );
565 
566     maDeactivateTimer.Stop();
567 
568     if( !mbDisposed )
569     {
570         OSL_FAIL("SlideshowImpl::~SlideshowImpl(), component was not disposed!");
571         disposing();
572     }
573 }
574 
disposing()575 void SAL_CALL SlideshowImpl::disposing()
576 {
577 #ifdef ENABLE_SDREMOTE
578     RemoteServer::presentationStopped();
579 #endif
580     if( mxShow.is() && mpDoc )
581         NotifyDocumentEvent(
582             *mpDoc,
583             "OnEndPresentation" );
584 
585     if( mbAutoSaveWasOn )
586         setAutoSaveState( true );
587 
588     if( mnEndShowEvent )
589         Application::RemoveUserEvent( mnEndShowEvent );
590     if( mnContextMenuEvent )
591         Application::RemoveUserEvent( mnContextMenuEvent );
592 
593     maInputFreezeTimer.Stop();
594 
595     SolarMutexGuard aSolarGuard;
596 
597     if( !mxShow.is() )
598         return;
599 
600     if( mxPresentation.is() )
601         mxPresentation->end();
602 
603     maUpdateTimer.Stop();
604 
605     removeShapeEvents();
606 
607     if( mxListenerProxy.is() )
608         mxListenerProxy->removeAsSlideShowListener();
609 
610     try
611     {
612         if( mxView.is() )
613             mxShow->removeView( mxView );
614 
615         Reference< XComponent > xComponent( mxShow, UNO_QUERY );
616         if( xComponent.is() )
617             xComponent->dispose();
618 
619         if( mxView.is() )
620             mxView->dispose();
621     }
622     catch( Exception& )
623     {
624         TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::stop()" );
625     }
626 
627     mxShow.clear();
628     mxView.clear();
629     mxListenerProxy.clear();
630     mpSlideController.reset();
631 
632     // take DrawView from presentation window, but give the old window back
633     if( mpShowWindow && mpView )
634         mpView->DeleteWindowFromPaintView( mpShowWindow->GetOutDev() );
635 
636     if( mpView )
637         mpView->SetAnimationPause( false );
638 
639     if( mpViewShell )
640     {
641         mpViewShell->SetActiveWindow(mpOldActiveWindow);
642         if (mpShowWindow)
643             mpShowWindow->SetViewShell( nullptr );
644     }
645 
646     if( mpView )
647         mpView->InvalidateAllWin();
648 
649     if( maPresSettings.mbFullScreen )
650     {
651 #if HAVE_FEATURE_SCRIPTING
652         // restore StarBASICErrorHdl
653         StarBASIC::SetGlobalErrorHdl(maStarBASICGlobalErrorHdl);
654         maStarBASICGlobalErrorHdl = Link<StarBASIC*,bool>();
655 #endif
656     }
657     else
658     {
659         if( mpShowWindow )
660             mpShowWindow->Hide();
661     }
662 
663     if( meAnimationMode == ANIMATIONMODE_SHOW )
664     {
665         mpDocSh->SetSlotFilter();
666         mpDocSh->ApplySlotFilter();
667 
668         Help::EnableContextHelp();
669         Help::EnableExtHelp();
670 
671         showChildWindows();
672         mnChildMask = 0;
673     }
674 
675     // show current window again
676     if( mpViewShell && dynamic_cast< PresentationViewShell *>( mpViewShell ) ==  nullptr)
677     {
678         if( meAnimationMode == ANIMATIONMODE_SHOW )
679         {
680             mpViewShell->GetViewShellBase().ShowUIControls (true);
681             mpPaneHider.reset();
682         }
683         else if( meAnimationMode == ANIMATIONMODE_PREVIEW )
684         {
685             mpViewShell->ShowUIControls(true);
686         }
687     }
688 
689     if( mpShowWindow )
690         mpShowWindow->Hide();
691     mpShowWindow.disposeAndClear();
692 
693     if ( mpViewShell )
694     {
695         if( meAnimationMode == ANIMATIONMODE_SHOW )
696         {
697             ::sd::Window* pActWin = mpViewShell->GetActiveWindow();
698 
699             if (pActWin)
700             {
701                 Size aVisSizePixel = pActWin->GetOutputSizePixel();
702                 ::tools::Rectangle aVisAreaWin = pActWin->PixelToLogic( ::tools::Rectangle( Point(0,0), aVisSizePixel) );
703                 mpViewShell->VisAreaChanged(aVisAreaWin);
704                 if (mpView)
705                     mpView->VisAreaChanged(pActWin->GetOutDev());
706                 pActWin->GrabFocus();
707             }
708         }
709 
710         // restart the custom show dialog if he started us
711         if( mpViewShell->IsStartShowWithDialog() && getDispatcher() )
712         {
713             mpViewShell->SetStartShowWithDialog( false );
714             getDispatcher()->Execute( SID_CUSTOMSHOW_DLG, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD );
715         }
716 
717         mpViewShell->GetViewShellBase().UpdateBorder(true);
718     }
719 
720     if( mpShowWindow )
721     {
722         mpShowWindow.disposeAndClear();
723     }
724 
725     setActiveXToolbarsVisible( true );
726 
727     mbDisposed = true;
728 }
729 
startPreview(const Reference<XDrawPage> & xDrawPage,const Reference<XAnimationNode> & xAnimationNode,vcl::Window * pParent)730 bool SlideshowImpl::startPreview(
731         const Reference< XDrawPage >& xDrawPage,
732         const Reference< XAnimationNode >& xAnimationNode,
733         vcl::Window * pParent )
734 {
735     bool bRet = false;
736 
737     try
738     {
739         const Reference<lang::XServiceInfo> xServiceInfo( xDrawPage, UNO_QUERY );
740         if (xServiceInfo.is()) {
741             const Sequence<OUString> supportedServices(
742                 xServiceInfo->getSupportedServiceNames() );
743             if (comphelper::findValue(supportedServices, "com.sun.star.drawing.MasterPage") != -1) {
744                 OSL_FAIL("sd::SlideshowImpl::startPreview() "
745                           "not allowed on master page!");
746                 return false;
747             }
748         }
749 
750         mxPreviewDrawPage = xDrawPage;
751         mxPreviewAnimationNode = xAnimationNode;
752         meAnimationMode = ANIMATIONMODE_PREVIEW;
753 
754         maPresSettings.mbAll = false;
755         maPresSettings.mbEndless = false;
756         maPresSettings.mbCustomShow = false;
757         maPresSettings.mbManual = false;
758         maPresSettings.mbMouseVisible = false;
759         maPresSettings.mbMouseAsPen = false;
760         maPresSettings.mbLockedPages = false;
761         maPresSettings.mbAlwaysOnTop = false;
762         maPresSettings.mbFullScreen = false;
763         maPresSettings.mbAnimationAllowed = true;
764         maPresSettings.mnPauseTimeout = 0;
765         maPresSettings.mbShowPauseLogo = false;
766 
767         Reference< XDrawPagesSupplier > xDrawPages( mpDoc->getUnoModel(), UNO_QUERY_THROW );
768         Reference< XIndexAccess > xSlides( xDrawPages->getDrawPages(), UNO_QUERY_THROW );
769         mpSlideController = std::make_shared<AnimationSlideController>( xSlides, AnimationSlideController::PREVIEW );
770 
771         sal_Int32 nSlideNumber = 0;
772         Reference< XPropertySet > xSet( mxPreviewDrawPage, UNO_QUERY_THROW );
773         xSet->getPropertyValue( "Number" ) >>= nSlideNumber;
774         mpSlideController->insertSlideNumber( nSlideNumber-1 );
775         mpSlideController->setPreviewNode( xAnimationNode );
776 
777         mpShowWindow = VclPtr<ShowWindow>::Create( this, ((pParent == nullptr) && mpViewShell) ?  mpParentWindow.get() : pParent );
778         if( mpViewShell )
779         {
780             mpViewShell->SetActiveWindow( mpShowWindow );
781             mpShowWindow->SetViewShell (mpViewShell);
782             mpViewShell->ShowUIControls (false);
783         }
784 
785         if( mpView )
786         {
787             mpView->AddWindowToPaintView( mpShowWindow->GetOutDev(), nullptr );
788             mpView->SetAnimationPause( true );
789         }
790 
791         // call resize handler
792         if( pParent )
793         {
794             maPresSize = pParent->GetSizePixel();
795         }
796         else if( mpViewShell )
797         {
798             ::tools::Rectangle aContentRect (mpViewShell->GetViewShellBase().getClientRectangle());
799             if (AllSettings::GetLayoutRTL())
800             {
801                 aContentRect.SetLeft( aContentRect.Right() );
802                 aContentRect.AdjustRight(aContentRect.Right() );
803             }
804             maPresSize = aContentRect.GetSize();
805             mpShowWindow->SetPosPixel( aContentRect.TopLeft() );
806         }
807         else
808         {
809             OSL_FAIL("sd::SlideshowImpl::startPreview(), I need either a parent window or a viewshell!");
810         }
811         resize( maPresSize );
812 
813         sal_Int32 nPropertyCount = 1;
814         if( mxPreviewAnimationNode.is() )
815             nPropertyCount++;
816 
817         Sequence< beans::PropertyValue > aProperties(nPropertyCount);
818         aProperties[0].Name = "AutomaticAdvancement";
819         aProperties[0].Value <<= 1.0; // one second timeout
820 
821         if( mxPreviewAnimationNode.is() )
822         {
823             aProperties[1].Name = "NoSlideTransitions";
824             aProperties[1].Value <<= true;
825         }
826 
827         bRet = startShowImpl( aProperties );
828 
829         if( mpShowWindow != nullptr && meAnimationMode == ANIMATIONMODE_PREVIEW )
830             mpShowWindow->SetPreviewMode();
831 
832     }
833     catch( Exception& )
834     {
835         TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::startPreview()" );
836         bRet = false;
837     }
838 
839     return bRet;
840 }
841 
startShow(PresentationSettingsEx const * pPresSettings)842 bool SlideshowImpl::startShow( PresentationSettingsEx const * pPresSettings )
843 {
844     const rtl::Reference<SlideshowImpl> xKeepAlive(this);
845 
846     DBG_ASSERT( !mxShow.is(), "sd::SlideshowImpl::startShow(), called twice!" );
847     if( mxShow.is() )
848         return true;
849     DBG_ASSERT( mpParentWindow!=nullptr, "sd::SlideshowImpl::startShow() called without parent window" );
850     if (mpParentWindow == nullptr)
851         return false;
852 
853     // Autoplay (pps/ppsx)
854     if (mpViewShell->GetDoc()->IsStartWithPresentation()){
855         mpViewShell->GetDoc()->SetExitAfterPresenting(true);
856     }
857 
858     bool bRet = false;
859 
860     try
861     {
862         if( pPresSettings )
863         {
864             maPresSettings = *pPresSettings;
865             mbRehearseTimings = pPresSettings->mbRehearseTimings;
866         }
867 
868         OUString  aPresSlide( maPresSettings.maPresPage );
869         SdPage* pStartPage = mpViewShell->GetActualPage();
870         bool    bStartWithActualSlide =  pStartPage;
871 
872         // times should be measured?
873         if( mbRehearseTimings )
874         {
875             maPresSettings.mbEndless = false;
876             maPresSettings.mbManual = true;
877             maPresSettings.mbMouseVisible = true;
878             maPresSettings.mbMouseAsPen = false;
879             maPresSettings.mnPauseTimeout = 0;
880             maPresSettings.mbShowPauseLogo = false;
881         }
882 
883         if( pStartPage )
884         {
885             if( pStartPage->GetPageKind() == PageKind::Notes )
886             {
887                 // we are in notes page mode, so get
888                 // the corresponding draw page
889                 const sal_uInt16 nPgNum = ( pStartPage->GetPageNum() - 2 ) >> 1;
890                 pStartPage = mpDoc->GetSdPage( nPgNum, PageKind::Standard );
891             }
892         }
893 
894         if( bStartWithActualSlide )
895         {
896             if ( aPresSlide.isEmpty())
897             {
898                 // no preset slide yet, so pick current on one
899                 aPresSlide = pStartPage->GetName();
900                 // if the starting slide is hidden, we can't set slide controller to ALL mode
901                 maPresSettings.mbAll = !pStartPage->IsExcluded();
902             }
903 
904             if( meAnimationMode != ANIMATIONMODE_SHOW )
905             {
906                 if( pStartPage->GetPageKind() == PageKind::Standard )
907                 {
908                     maPresSettings.mbAll = false;
909                 }
910             }
911         }
912 
913         // build page list
914         createSlideList( maPresSettings.mbAll, aPresSlide );
915 
916         // remember Slide number from where the show was started
917         if( pStartPage )
918             mnRestoreSlide = ( pStartPage->GetPageNum() - 1 ) / 2;
919 
920         if( mpSlideController->hasSlides() )
921         {
922             // hide child windows
923             hideChildWindows();
924 
925             mpShowWindow = VclPtr<ShowWindow>::Create( this, mpParentWindow );
926             mpShowWindow->SetMouseAutoHide( !maPresSettings.mbMouseVisible );
927             mpViewShell->SetActiveWindow( mpShowWindow );
928             mpShowWindow->SetViewShell (mpViewShell);
929             mpViewShell->GetViewShellBase().ShowUIControls (false);
930             // Hide the side panes for in-place presentations.
931             if ( ! maPresSettings.mbFullScreen)
932                 mpPaneHider.reset(new PaneHider(*mpViewShell,this));
933 
934             // these Slots are forbidden in other views for this document
935             if( mpDocSh )
936             {
937                 mpDocSh->SetSlotFilter( true, pAllowed );
938                 mpDocSh->ApplySlotFilter();
939             }
940 
941             Help::DisableContextHelp();
942             Help::DisableExtHelp();
943 
944             if( maPresSettings.mbFullScreen )
945             {
946 #if HAVE_FEATURE_SCRIPTING
947                 // disable basic ide error handling
948                 maStarBASICGlobalErrorHdl = StarBASIC::GetGlobalErrorHdl();
949                 StarBASIC::SetGlobalErrorHdl( Link<StarBASIC*,bool>() );
950 #endif
951             }
952 
953             // call resize handler
954             maPresSize = mpParentWindow->GetSizePixel();
955             if (!maPresSettings.mbFullScreen)
956             {
957                 const ::tools::Rectangle& aClientRect = mpViewShell->GetViewShellBase().getClientRectangle();
958                 maPresSize = aClientRect.GetSize();
959                 mpShowWindow->SetPosPixel( aClientRect.TopLeft() );
960                 resize( maPresSize );
961             }
962 
963             // #i41824#
964             // Note: In FullScreen Mode the OS (window manager) sends a resize to
965             // the WorkWindow once it actually resized it to full size.  The
966             // WorkWindow propagates the resize to the DrawViewShell which calls
967             // resize() at the SlideShow (this).  Calling resize here results in a
968             // temporary display of a black window in the window's default size
969 
970             if( mpView )
971             {
972                 mpView->AddWindowToPaintView( mpShowWindow->GetOutDev(), nullptr );
973                 mpView->SetAnimationPause( true );
974             }
975 
976             SfxBindings* pBindings = getBindings();
977             if( pBindings )
978             {
979                 pBindings->Invalidate( SID_PRESENTATION );
980                 pBindings->Invalidate( SID_REHEARSE_TIMINGS );
981             }
982 
983             // Defer the sd::ShowWindow's GrabFocus to SlideShow::activate. so that the accessible event can be fired correctly.
984             //mpShowWindow->GrabFocus();
985 
986             std::vector<beans::PropertyValue> aProperties;
987             aProperties.reserve( 4 );
988 
989             aProperties.emplace_back( "AdvanceOnClick" ,
990                     -1, Any( !maPresSettings.mbLockedPages ),
991                     beans::PropertyState_DIRECT_VALUE );
992 
993             aProperties.emplace_back( "ImageAnimationsAllowed" ,
994                     -1, Any( maPresSettings.mbAnimationAllowed ),
995                     beans::PropertyState_DIRECT_VALUE );
996 
997             const bool bZOrderEnabled(
998                 SD_MOD()->GetSdOptions( mpDoc->GetDocumentType() )->IsSlideshowRespectZOrder() );
999             aProperties.emplace_back( "DisableAnimationZOrder" ,
1000                     -1, Any( !bZOrderEnabled ),
1001                     beans::PropertyState_DIRECT_VALUE );
1002 
1003             aProperties.emplace_back( "ForceManualAdvance" ,
1004                     -1, Any( maPresSettings.mbManual ),
1005                     beans::PropertyState_DIRECT_VALUE );
1006 
1007             if( mbUsePen )
1008              {
1009                 aProperties.emplace_back( "UserPaintColor" ,
1010                         // User paint color is black by default.
1011                         -1, Any( mnUserPaintColor ),
1012                         beans::PropertyState_DIRECT_VALUE );
1013 
1014                 aProperties.emplace_back( "UserPaintStrokeWidth" ,
1015                         // User paint color is black by default.
1016                         -1, Any( mdUserPaintStrokeWidth ),
1017                         beans::PropertyState_DIRECT_VALUE );
1018             }
1019 
1020             if (mbRehearseTimings) {
1021                 aProperties.emplace_back( "RehearseTimings" ,
1022                         -1, Any(true), beans::PropertyState_DIRECT_VALUE );
1023             }
1024 
1025             bRet = startShowImpl( Sequence<beans::PropertyValue>(
1026                                       aProperties.data(), aProperties.size() ) );
1027 
1028         }
1029 
1030         setActiveXToolbarsVisible( false );
1031     }
1032     catch (const Exception&)
1033     {
1034         TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::startShow()" );
1035         bRet = false;
1036     }
1037 
1038     return bRet;
1039 }
1040 
startShowImpl(const Sequence<beans::PropertyValue> & aProperties)1041 bool SlideshowImpl::startShowImpl( const Sequence< beans::PropertyValue >& aProperties )
1042 {
1043     try
1044     {
1045         mxShow.set( createSlideShow(), UNO_SET_THROW );
1046 
1047         mxView = new SlideShowView(
1048                                              *mpShowWindow,
1049                                              mpDoc,
1050                                              meAnimationMode,
1051                                              this,
1052                                              maPresSettings.mbFullScreen);
1053 
1054         // try add wait symbol to properties:
1055         const Reference<rendering::XSpriteCanvas> xSpriteCanvas(
1056             mxView->getCanvas() );
1057         if (xSpriteCanvas.is())
1058         {
1059             BitmapEx waitSymbolBitmap(BMP_WAIT_ICON);
1060             const Reference<rendering::XBitmap> xBitmap(
1061                 vcl::unotools::xBitmapFromBitmapEx( waitSymbolBitmap ) );
1062             if (xBitmap.is())
1063             {
1064                 mxShow->setProperty(
1065                     beans::PropertyValue( "WaitSymbolBitmap" ,
1066                         -1,
1067                         makeAny( xBitmap ),
1068                         beans::PropertyState_DIRECT_VALUE ) );
1069             }
1070 
1071             BitmapEx pointerSymbolBitmap(BMP_POINTER_ICON);
1072             const Reference<rendering::XBitmap> xPointerBitmap(
1073                 vcl::unotools::xBitmapFromBitmapEx( pointerSymbolBitmap ) );
1074             if (xPointerBitmap.is())
1075             {
1076                 mxShow->setProperty(
1077                     beans::PropertyValue( "PointerSymbolBitmap" ,
1078                         -1,
1079                         makeAny( xPointerBitmap ),
1080                         beans::PropertyState_DIRECT_VALUE ) );
1081             }
1082         }
1083 
1084         for( const auto& rProp : aProperties )
1085             mxShow->setProperty( rProp );
1086 
1087         mxShow->addView( mxView );
1088 
1089         mxListenerProxy.set( new SlideShowListenerProxy( this, mxShow ) );
1090         mxListenerProxy->addAsSlideShowListener();
1091 
1092         NotifyDocumentEvent(
1093             *mpDoc,
1094             "OnStartPresentation");
1095         displaySlideIndex( mpSlideController->getStartSlideIndex() );
1096 
1097         return true;
1098     }
1099     catch( Exception& )
1100     {
1101         TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::startShowImpl()" );
1102         return false;
1103     }
1104 }
1105 
1106 /** called only by the slideshow view when the first paint event occurs.
1107     This actually starts the slideshow. */
onFirstPaint()1108 void SlideshowImpl::onFirstPaint()
1109 {
1110     if( mpShowWindow )
1111     {
1112         /*
1113         mpShowWindow->SetBackground( Wallpaper( COL_BLACK ) );
1114         mpShowWindow->Erase();
1115         mpShowWindow->SetBackground();
1116         */
1117     }
1118 
1119     SolarMutexGuard aSolarGuard;
1120     maUpdateTimer.SetTimeout( sal_uLong(100) );
1121     maUpdateTimer.Start();
1122 }
1123 
paint()1124 void SlideshowImpl::paint()
1125 {
1126     if( mxView.is() ) try
1127     {
1128         awt::PaintEvent aEvt;
1129         // aEvt.UpdateRect = TODO
1130         mxView->paint( aEvt );
1131     }
1132     catch( Exception& )
1133     {
1134         TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::paint()" );
1135     }
1136 }
1137 
addSlideShowListener(const Reference<XSlideShowListener> & xListener)1138 void SAL_CALL SlideshowImpl::addSlideShowListener( const Reference< XSlideShowListener >& xListener )
1139 {
1140     if( mxListenerProxy.is() )
1141         mxListenerProxy->addSlideShowListener( xListener );
1142 }
1143 
removeSlideShowListener(const Reference<XSlideShowListener> & xListener)1144 void SAL_CALL SlideshowImpl::removeSlideShowListener( const Reference< XSlideShowListener >& xListener )
1145 {
1146     if( mxListenerProxy.is() )
1147         mxListenerProxy->removeSlideShowListener( xListener );
1148 }
1149 
slideEnded(const bool bReverse)1150 void SlideshowImpl::slideEnded(const bool bReverse)
1151 {
1152     if (bReverse)
1153         gotoPreviousSlide(true);
1154     else
1155         gotoNextSlide();
1156 }
1157 
swipe(const CommandSwipeData & rSwipeData)1158 bool SlideshowImpl::swipe(const CommandSwipeData &rSwipeData)
1159 {
1160     if (mbUsePen || mnContextMenuEvent)
1161         return false;
1162     double nVelocityX = rSwipeData.getVelocityX();
1163     // tdf#108475 make it swipe only if some reasonable movement was involved
1164     if (fabs(nVelocityX) < 50)
1165         return false;
1166     if (nVelocityX > 0)
1167     {
1168         gotoPreviousSlide();
1169     }
1170     else
1171     {
1172         gotoNextEffect();
1173     }
1174     //a swipe is followed by a mouse up, tell the view to ignore that mouse up as we've reacted
1175     //to the swipe instead
1176     mxView->ignoreNextMouseReleased();
1177     return true;
1178 }
1179 
longpress(const CommandLongPressData & rLongPressData)1180 bool SlideshowImpl::longpress(const CommandLongPressData &rLongPressData)
1181 {
1182     if (mnContextMenuEvent)
1183         return false;
1184 
1185     maPopupMousePos = Point(rLongPressData.getX(), rLongPressData.getY());
1186     mnContextMenuEvent = Application::PostUserEvent( LINK( this, SlideshowImpl, ContextMenuHdl ) );
1187 
1188     return true;
1189 }
1190 
removeShapeEvents()1191 void SlideshowImpl::removeShapeEvents()
1192 {
1193     if( !(mxShow.is() && mxListenerProxy.is()) )
1194         return;
1195 
1196     try
1197     {
1198         for( const auto& rEntry : maShapeEventMap )
1199         {
1200             mxListenerProxy->removeShapeEventListener( rEntry.first );
1201             mxShow->setShapeCursor( rEntry.first, awt::SystemPointer::ARROW );
1202         }
1203 
1204         maShapeEventMap.clear();
1205     }
1206     catch( Exception& )
1207     {
1208         TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::removeShapeEvents()" );
1209     }
1210 }
1211 
registerShapeEvents(sal_Int32 nSlideNumber)1212 void SlideshowImpl::registerShapeEvents(sal_Int32 nSlideNumber)
1213 {
1214     if( nSlideNumber < 0 )
1215         return;
1216 
1217     try
1218     {
1219         Reference< XDrawPagesSupplier > xDrawPages( mxModel, UNO_QUERY_THROW );
1220         Reference< XIndexAccess > xPages( xDrawPages->getDrawPages(), UNO_QUERY_THROW );
1221 
1222         Reference< XShapes > xDrawPage;
1223         xPages->getByIndex(nSlideNumber) >>= xDrawPage;
1224 
1225         if( xDrawPage.is() )
1226         {
1227             Reference< XMasterPageTarget > xMasterPageTarget( xDrawPage, UNO_QUERY );
1228             if( xMasterPageTarget.is() )
1229             {
1230                 Reference< XShapes > xMasterPage = xMasterPageTarget->getMasterPage();
1231                 if( xMasterPage.is() )
1232                     registerShapeEvents( xMasterPage );
1233             }
1234             registerShapeEvents( xDrawPage );
1235         }
1236     }
1237     catch( Exception& )
1238     {
1239         TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::registerShapeEvents()" );
1240     }
1241 }
1242 
registerShapeEvents(Reference<XShapes> const & xShapes)1243 void SlideshowImpl::registerShapeEvents( Reference< XShapes > const & xShapes )
1244 {
1245     try
1246     {
1247         const sal_Int32 nShapeCount = xShapes->getCount();
1248         sal_Int32 nShape;
1249         for( nShape = 0; nShape < nShapeCount; nShape++ )
1250         {
1251             Reference< XShape > xShape;
1252             xShapes->getByIndex( nShape ) >>= xShape;
1253 
1254             if( xShape.is() && xShape->getShapeType() == "com.sun.star.drawing.GroupShape" )
1255             {
1256                 Reference< XShapes > xSubShapes( xShape, UNO_QUERY );
1257                 if( xSubShapes.is() )
1258                     registerShapeEvents( xSubShapes );
1259             }
1260 
1261             Reference< XPropertySet > xSet( xShape, UNO_QUERY );
1262             if( !xSet.is() )
1263                 continue;
1264 
1265             Reference< XPropertySetInfo > xSetInfo( xSet->getPropertySetInfo() );
1266             if( !xSetInfo.is() || !xSetInfo->hasPropertyByName( gsOnClick ) )
1267                 continue;
1268 
1269             WrappedShapeEventImplPtr pEvent = std::make_shared<WrappedShapeEventImpl>();
1270             xSet->getPropertyValue( gsOnClick ) >>= pEvent->meClickAction;
1271 
1272             switch( pEvent->meClickAction )
1273             {
1274             case ClickAction_PREVPAGE:
1275             case ClickAction_NEXTPAGE:
1276             case ClickAction_FIRSTPAGE:
1277             case ClickAction_LASTPAGE:
1278             case ClickAction_STOPPRESENTATION:
1279                 break;
1280             case ClickAction_BOOKMARK:
1281                 if( xSetInfo->hasPropertyByName( gsBookmark ) )
1282                     xSet->getPropertyValue( gsBookmark ) >>= pEvent->maStrBookmark;
1283                 if( getSlideNumberForBookmark( pEvent->maStrBookmark ) == -1 )
1284                     continue;
1285                 break;
1286             case ClickAction_DOCUMENT:
1287             case ClickAction_SOUND:
1288             case ClickAction_PROGRAM:
1289             case ClickAction_MACRO:
1290                 if( xSetInfo->hasPropertyByName( gsBookmark ) )
1291                     xSet->getPropertyValue( gsBookmark ) >>= pEvent->maStrBookmark;
1292                 break;
1293             case ClickAction_VERB:
1294                 if( xSetInfo->hasPropertyByName( gsVerb ) )
1295                     xSet->getPropertyValue( gsVerb ) >>= pEvent->mnVerb;
1296                 break;
1297             default:
1298                 continue; // skip all others
1299             }
1300 
1301             maShapeEventMap[ xShape ] = pEvent;
1302 
1303             if( mxListenerProxy.is() )
1304                 mxListenerProxy->addShapeEventListener( xShape );
1305             mxShow->setShapeCursor( xShape, awt::SystemPointer::REFHAND );
1306         }
1307     }
1308     catch( Exception& )
1309     {
1310         TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::registerShapeEvents()" );
1311     }
1312 }
1313 
displayCurrentSlide(const bool bSkipAllMainSequenceEffects)1314 void SlideshowImpl::displayCurrentSlide (const bool bSkipAllMainSequenceEffects)
1315 {
1316     stopSound();
1317     removeShapeEvents();
1318 
1319     if( mpSlideController && mxShow.is() )
1320     {
1321         Reference< XDrawPagesSupplier > xDrawPages( mpDoc->getUnoModel(),
1322                                                     UNO_QUERY_THROW );
1323         mpSlideController->displayCurrentSlide( mxShow, xDrawPages, bSkipAllMainSequenceEffects );
1324         registerShapeEvents(mpSlideController->getCurrentSlideNumber());
1325         update();
1326 
1327     }
1328     // send out page change event and notify to update all acc info for current page
1329     if (mpViewShell)
1330     {
1331         sal_Int32 currentPageIndex = getCurrentSlideIndex();
1332         mpViewShell->fireSwitchCurrentPage(currentPageIndex);
1333         mpViewShell->NotifyAccUpdate();
1334     }
1335 }
1336 
endPresentation()1337 void SlideshowImpl::endPresentation()
1338 {
1339     if( maPresSettings.mbMouseAsPen)
1340     {
1341         Reference< XMultiServiceFactory > xDocFactory(mpDoc->getUnoModel(), UNO_QUERY );
1342         if( xDocFactory.is() )
1343             mxShow->registerUserPaintPolygons(xDocFactory);
1344     }
1345 
1346     if( !mnEndShowEvent )
1347         mnEndShowEvent = Application::PostUserEvent( LINK(this, SlideshowImpl, endPresentationHdl) );
1348 }
1349 
IMPL_LINK_NOARG(SlideshowImpl,endPresentationHdl,void *,void)1350 IMPL_LINK_NOARG(SlideshowImpl, endPresentationHdl, void*, void)
1351 {
1352     mnEndShowEvent = nullptr;
1353 
1354     if( mxPresentation.is() )
1355         mxPresentation->end();
1356 }
1357 
pause()1358 void SAL_CALL SlideshowImpl::pause()
1359 {
1360     SolarMutexGuard aSolarGuard;
1361 
1362     if( mbIsPaused )
1363         return;
1364 
1365     try
1366     {
1367         mbIsPaused = true;
1368         if( mxShow.is() )
1369         {
1370             mxShow->pause(true);
1371 
1372             if( mxListenerProxy.is() )
1373                 mxListenerProxy->paused();
1374         }
1375     }
1376     catch( Exception& )
1377     {
1378         TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::pause()" );
1379     }
1380 }
1381 
resume()1382 void SAL_CALL SlideshowImpl::resume()
1383 {
1384     SolarMutexGuard aSolarGuard;
1385 
1386     if( mbIsPaused ) try
1387     {
1388         if( mpShowWindow->GetShowWindowMode() == SHOWWINDOWMODE_BLANK )
1389         {
1390             mpShowWindow->RestartShow();
1391         }
1392         else
1393         {
1394             mbIsPaused = false;
1395             if( mxShow.is() )
1396             {
1397                 mxShow->pause(false);
1398                 update();
1399 
1400                 if( mxListenerProxy.is() )
1401                     mxListenerProxy->resumed();
1402             }
1403         }
1404     }
1405     catch( Exception& )
1406     {
1407         TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::resume()" );
1408     }
1409 #ifdef ENABLE_SDREMOTE
1410     RemoteServer::presentationStarted( this );
1411 #endif
1412 }
1413 
isPaused()1414 sal_Bool SAL_CALL SlideshowImpl::isPaused()
1415 {
1416     SolarMutexGuard aSolarGuard;
1417     return mbIsPaused;
1418 }
1419 
blankScreen(sal_Int32 nColor)1420 void SAL_CALL SlideshowImpl::blankScreen( sal_Int32 nColor )
1421 {
1422     SolarMutexGuard aSolarGuard;
1423 
1424     if( mpShowWindow && mpSlideController )
1425     {
1426         if( mpShowWindow->SetBlankMode( mpSlideController->getCurrentSlideIndex(), Color(ColorTransparency, nColor) ) )
1427         {
1428             pause();
1429         }
1430     }
1431 }
1432 
1433 // XShapeEventListener
1434 
click(const Reference<XShape> & xShape)1435 void SlideshowImpl::click( const Reference< XShape >& xShape )
1436 {
1437     SolarMutexGuard aSolarGuard;
1438 
1439     WrappedShapeEventImplPtr pEvent = maShapeEventMap[xShape];
1440     if( !pEvent )
1441         return;
1442 
1443     switch( pEvent->meClickAction )
1444     {
1445     case ClickAction_PREVPAGE:          gotoPreviousSlide();        break;
1446     case ClickAction_NEXTPAGE:          gotoNextSlide();            break;
1447     case ClickAction_FIRSTPAGE:         gotoFirstSlide();           break;
1448     case ClickAction_LASTPAGE:          gotoLastSlide();            break;
1449     case ClickAction_STOPPRESENTATION:  endPresentation();          break;
1450     case ClickAction_BOOKMARK:
1451     {
1452         gotoBookmark( pEvent->maStrBookmark );
1453     }
1454     break;
1455     case ClickAction_SOUND:
1456     {
1457 #if HAVE_FEATURE_AVMEDIA
1458         try
1459         {
1460             mxPlayer.set(avmedia::MediaWindow::createPlayer(pEvent->maStrBookmark, ""/*TODO?*/), uno::UNO_SET_THROW );
1461             mxPlayer->start();
1462         }
1463         catch( uno::Exception& )
1464         {
1465             TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::click()" );
1466         }
1467 #endif
1468     }
1469     break;
1470 
1471     case ClickAction_DOCUMENT:
1472     {
1473         OUString aBookmark( pEvent->maStrBookmark );
1474 
1475         sal_Int32 nPos = aBookmark.indexOf( '#' );
1476         if( nPos >= 0 )
1477         {
1478             OUString aURL( aBookmark.copy( 0, nPos+1 ) );
1479             OUString aName( aBookmark.copy( nPos+1 ) );
1480             aURL += getUiNameFromPageApiNameImpl( aName );
1481             aBookmark = aURL;
1482         }
1483 
1484         mpDocSh->OpenBookmark( aBookmark );
1485     }
1486     break;
1487 
1488     case ClickAction_PROGRAM:
1489     {
1490         INetURLObject aURL(
1491             ::URIHelper::SmartRel2Abs(
1492                 INetURLObject(mpDocSh->GetMedium()->GetBaseURL()),
1493                 pEvent->maStrBookmark, ::URIHelper::GetMaybeFileHdl(), true,
1494                 false, INetURLObject::EncodeMechanism::WasEncoded,
1495                 INetURLObject::DecodeMechanism::Unambiguous ) );
1496 
1497         if( INetProtocol::File == aURL.GetProtocol() )
1498         {
1499             SfxStringItem aUrl( SID_FILE_NAME, aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
1500             SfxBoolItem aBrowsing( SID_BROWSE, true );
1501 
1502             SfxViewFrame* pViewFrm = SfxViewFrame::Current();
1503             if (pViewFrm)
1504             {
1505                 pViewFrm->GetDispatcher()->ExecuteList( SID_OPENDOC,
1506                     SfxCallMode::ASYNCHRON | SfxCallMode::RECORD,
1507                     { &aUrl, &aBrowsing });
1508             }
1509         }
1510     }
1511     break;
1512 
1513     case presentation::ClickAction_MACRO:
1514     {
1515         const OUString aMacro( pEvent->maStrBookmark );
1516 
1517         if ( SfxApplication::IsXScriptURL( aMacro ) )
1518         {
1519             Any aRet;
1520             Sequence< sal_Int16 > aOutArgsIndex;
1521             Sequence< Any > aOutArgs;
1522             Sequence< Any >* pInArgs = new Sequence< Any >(0);
1523             mpDocSh->CallXScript( aMacro, *pInArgs, aRet, aOutArgsIndex, aOutArgs);
1524         }
1525         else
1526         {
1527             // aMacro has the following syntax:
1528             // "Macroname.Modulname.Libname.Documentname" or
1529             // "Macroname.Modulname.Libname.Applicationname"
1530             sal_Int32 nIdx{ 0 };
1531             const OUString aMacroName = aMacro.getToken(0, '.', nIdx);
1532             const OUString aModulName = aMacro.getToken(0, '.', nIdx);
1533 
1534             // todo: is the limitation still given that only
1535             // Modulname+Macroname can be used here?
1536             OUString aExecMacro = aModulName + "." + aMacroName;
1537             mpDocSh->GetBasic()->Call(aExecMacro);
1538         }
1539     }
1540     break;
1541 
1542     case ClickAction_VERB:
1543     {
1544         // todo, better do it async?
1545         SdrObject* pObj = GetSdrObjectFromXShape( xShape );
1546         SdrOle2Obj* pOleObject = dynamic_cast< SdrOle2Obj* >(pObj);
1547         if (pOleObject && mpViewShell )
1548             mpViewShell->ActivateObject(pOleObject, pEvent->mnVerb);
1549     }
1550     break;
1551     default:
1552         break;
1553     }
1554 }
1555 
getSlideNumberForBookmark(const OUString & rStrBookmark)1556 sal_Int32 SlideshowImpl::getSlideNumberForBookmark( const OUString& rStrBookmark )
1557 {
1558     bool bIsMasterPage;
1559     OUString aBookmark = getUiNameFromPageApiNameImpl( rStrBookmark );
1560     sal_uInt16 nPgNum = mpDoc->GetPageByName( aBookmark, bIsMasterPage );
1561 
1562     if( nPgNum == SDRPAGE_NOTFOUND )
1563     {
1564         // Is the bookmark an object?
1565         SdrObject* pObj = mpDoc->GetObj( aBookmark );
1566 
1567         if( pObj )
1568         {
1569             nPgNum = pObj->getSdrPageFromSdrObject()->GetPageNum();
1570             bIsMasterPage = pObj->getSdrPageFromSdrObject()->IsMasterPage();
1571         }
1572     }
1573 
1574     if( (nPgNum == SDRPAGE_NOTFOUND) || bIsMasterPage || static_cast<SdPage*>(mpDoc->GetPage(nPgNum))->GetPageKind() != PageKind::Standard )
1575         return -1;
1576 
1577     return ( nPgNum - 1) >> 1;
1578 }
1579 
hyperLinkClicked(OUString const & aHyperLink)1580 void SlideshowImpl::hyperLinkClicked( OUString const& aHyperLink )
1581 {
1582     OUString aBookmark( aHyperLink );
1583 
1584     sal_Int32 nPos = aBookmark.indexOf( '#' );
1585     if( nPos >= 0 )
1586     {
1587         OUString aURL( aBookmark.copy( 0, nPos+1 ) );
1588         OUString aName( aBookmark.copy( nPos+1 ) );
1589         aURL += getUiNameFromPageApiNameImpl( aName );
1590         aBookmark = aURL;
1591     }
1592 
1593     mpDocSh->OpenBookmark( aBookmark );
1594 }
1595 
displaySlideNumber(sal_Int32 nSlideNumber)1596 void SlideshowImpl::displaySlideNumber( sal_Int32 nSlideNumber )
1597 {
1598     if( mpSlideController )
1599     {
1600         if( mpSlideController->jumpToSlideNumber( nSlideNumber ) )
1601         {
1602             displayCurrentSlide();
1603         }
1604     }
1605 }
1606 
1607 /** nSlideIndex == -1 displays current slide again */
displaySlideIndex(sal_Int32 nSlideIndex)1608 void SlideshowImpl::displaySlideIndex( sal_Int32 nSlideIndex )
1609 {
1610     if( mpSlideController )
1611     {
1612         if( (nSlideIndex == -1) || mpSlideController->jumpToSlideIndex( nSlideIndex ) )
1613         {
1614             displayCurrentSlide();
1615         }
1616     }
1617 }
1618 
jumpToBookmark(const OUString & sBookmark)1619 void SlideshowImpl::jumpToBookmark( const OUString& sBookmark )
1620 {
1621     sal_Int32 nSlideNumber = getSlideNumberForBookmark( sBookmark );
1622     if( nSlideNumber != -1 )
1623         displaySlideNumber( nSlideNumber );
1624 }
1625 
getCurrentSlideNumber() const1626 sal_Int32 SlideshowImpl::getCurrentSlideNumber() const
1627 {
1628     return mpSlideController ? mpSlideController->getCurrentSlideNumber() : -1;
1629 }
1630 
isEndless()1631 sal_Bool SAL_CALL SlideshowImpl::isEndless()
1632 {
1633     SolarMutexGuard aSolarGuard;
1634     return maPresSettings.mbEndless;
1635 }
1636 
update()1637 void SlideshowImpl::update()
1638 {
1639     startUpdateTimer();
1640 }
1641 
startUpdateTimer()1642 void SlideshowImpl::startUpdateTimer()
1643 {
1644     SolarMutexGuard aSolarGuard;
1645     maUpdateTimer.SetTimeout( 0 );
1646     maUpdateTimer.Start();
1647 }
1648 
1649 /** this timer is called 20ms after a new slide was displayed.
1650     This is used to unfreeze user input that was disabled after
1651     slide change to skip input that was buffered during slide
1652     transition preparation */
IMPL_LINK_NOARG(SlideshowImpl,ReadyForNextInputHdl,Timer *,void)1653 IMPL_LINK_NOARG(SlideshowImpl, ReadyForNextInputHdl, Timer *, void)
1654 {
1655     mbInputFreeze = false;
1656 }
1657 
1658 /** if I catch someone someday who calls this method by hand
1659     and not by using the timer, I will personally punish this
1660     person seriously, even if this person is me.
1661 */
IMPL_LINK_NOARG(SlideshowImpl,updateHdl,Timer *,void)1662 IMPL_LINK_NOARG(SlideshowImpl, updateHdl, Timer *, void)
1663 {
1664     updateSlideShow();
1665 }
1666 
updateSlideShow()1667 void SlideshowImpl::updateSlideShow()
1668 {
1669     // prevent me from deletion when recursing (App::EnableYieldMode does)
1670     const rtl::Reference<SlideshowImpl> xKeepAlive(this);
1671 
1672     Reference< XSlideShow > xShow( mxShow );
1673     if ( ! xShow.is())
1674         return;
1675 
1676     try
1677     {
1678         double fUpdate = 0.0;
1679         if( !xShow->update(fUpdate) )
1680             fUpdate = -1.0;
1681 
1682         if (mxShow.is() && (fUpdate >= 0.0))
1683         {
1684             if (::basegfx::fTools::equalZero(fUpdate))
1685             {
1686                 // Make sure idle tasks don't starve when we don't have to wait.
1687                 // Don't process any events generated after invoking the function.
1688                 Application::Reschedule(/*bHandleAllCurrentEvents=*/true);
1689             }
1690             else
1691             {
1692                 // Avoid busy loop when the previous call to update()
1693                 // returns a small positive number but not 0 (which is
1694                 // handled above).  Also, make sure that calls to update()
1695                 // have a minimum frequency.
1696                 // => Allow up to 60 frames per second.  Call at least once
1697                 // every 4 seconds.
1698                 const static sal_Int32 nMaximumFrameCount (60);
1699                 const static double nMinimumTimeout (1.0 / nMaximumFrameCount);
1700                 const static double nMaximumTimeout (4.0);
1701                 fUpdate = std::clamp(fUpdate, nMinimumTimeout, nMaximumTimeout);
1702 
1703                 // Make sure that the maximum frame count has not been set
1704                 // too high (only then conversion to milliseconds and long
1705                 // integer may lead to zero value.)
1706                 OSL_ASSERT(static_cast<sal_uLong>(fUpdate * 1000.0) > 0);
1707             }
1708 
1709             // Use our high resolution timers for the asynchronous callback.
1710             maUpdateTimer.SetTimeout(static_cast<sal_uLong>(fUpdate * 1000.0));
1711             maUpdateTimer.Start();
1712         }
1713     }
1714     catch( Exception& )
1715     {
1716         TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::updateSlideShow()" );
1717     }
1718 }
1719 
keyInput(const KeyEvent & rKEvt)1720 bool SlideshowImpl::keyInput(const KeyEvent& rKEvt)
1721 {
1722     if( !mxShow.is() || mbInputFreeze )
1723         return false;
1724 
1725     bool bRet = true;
1726 
1727     try
1728     {
1729         const int nKeyCode = rKEvt.GetKeyCode().GetCode();
1730         switch( nKeyCode )
1731         {
1732             case awt::Key::CONTEXTMENU:
1733                 if( !mnContextMenuEvent )
1734                 {
1735                     if( mpShowWindow )
1736                         maPopupMousePos = mpShowWindow->GetPointerState().maPos;
1737                     mnContextMenuEvent = Application::PostUserEvent( LINK( this, SlideshowImpl, ContextMenuHdl ) );
1738                 }
1739                 break;
1740 
1741             // cancel show
1742             case KEY_ESCAPE:
1743             case KEY_SUBTRACT:
1744                 // in case the user cancels the presentation, switch to current slide
1745                 // in edit mode
1746                 if( mpSlideController && (ANIMATIONMODE_SHOW == meAnimationMode) )
1747                 {
1748                     if( mpSlideController->getCurrentSlideNumber() != -1 )
1749                         mnRestoreSlide = mpSlideController->getCurrentSlideNumber();
1750                 }
1751                 endPresentation();
1752                 break;
1753 
1754             // advance show
1755             case KEY_PAGEDOWN:
1756                 if(rKEvt.GetKeyCode().IsMod2())
1757                 {
1758                     gotoNextSlide();
1759                     break;
1760                 }
1761                 [[fallthrough]];
1762             case KEY_SPACE:
1763             case KEY_RIGHT:
1764             case KEY_DOWN:
1765                 gotoNextEffect();
1766                 break;
1767 
1768             case KEY_RETURN:
1769             {
1770                 if( !maCharBuffer.isEmpty() )
1771                 {
1772                     if( mpSlideController )
1773                     {
1774                         if( mpSlideController->jumpToSlideNumber( maCharBuffer.toInt32() - 1 ) )
1775                             displayCurrentSlide();
1776                     }
1777                     maCharBuffer.clear();
1778                 }
1779                 else
1780                 {
1781                     gotoNextEffect();
1782                 }
1783             }
1784             break;
1785 
1786             // numeric: add to buffer
1787             case KEY_0:
1788             case KEY_1:
1789             case KEY_2:
1790             case KEY_3:
1791             case KEY_4:
1792             case KEY_5:
1793             case KEY_6:
1794             case KEY_7:
1795             case KEY_8:
1796             case KEY_9:
1797                 maCharBuffer += OUStringChar( rKEvt.GetCharCode() );
1798                 break;
1799 
1800             case KEY_PAGEUP:
1801                 if(rKEvt.GetKeyCode().IsMod2())
1802                 {
1803                     gotoPreviousSlide();
1804                     break;
1805                 }
1806                 [[fallthrough]];
1807             case KEY_LEFT:
1808             case KEY_UP:
1809             case KEY_BACKSPACE:
1810                 gotoPreviousEffect();
1811                 break;
1812 
1813             case KEY_P:
1814                 setUsePen( !mbUsePen );
1815                 break;
1816 
1817             case KEY_E:
1818                 setEraseAllInk( true );
1819                 updateSlideShow();
1820                 break;
1821 
1822             case KEY_HOME:
1823                 gotoFirstSlide();
1824                 break;
1825 
1826             case KEY_END:
1827                 gotoLastSlide();
1828                 break;
1829 
1830             case KEY_B:
1831             case KEY_W:
1832             case KEY_POINT:
1833             case KEY_COMMA:
1834             {
1835                 blankScreen( ((nKeyCode == KEY_W ) || (nKeyCode == KEY_COMMA)) ? 0x00ffffff : 0x00000000 );
1836             }
1837             break;
1838 
1839             default:
1840                 bRet = false;
1841             break;
1842         }
1843     }
1844     catch( Exception& )
1845     {
1846         bRet = false;
1847         TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::keyInput()" );
1848     }
1849 
1850     return bRet;
1851 }
1852 
IMPL_LINK(SlideshowImpl,EventListenerHdl,VclSimpleEvent &,rSimpleEvent,void)1853 IMPL_LINK( SlideshowImpl, EventListenerHdl, VclSimpleEvent&, rSimpleEvent, void )
1854 {
1855     if( !mxShow.is() || mbInputFreeze )
1856         return;
1857 
1858     if( !((rSimpleEvent.GetId() == VclEventId::WindowCommand) && static_cast<VclWindowEvent*>(&rSimpleEvent)->GetData()) )
1859         return;
1860 
1861     const CommandEvent& rEvent = *static_cast<const CommandEvent*>(static_cast<VclWindowEvent*>(&rSimpleEvent)->GetData());
1862 
1863     if( rEvent.GetCommand() != CommandEventId::Media )
1864         return;
1865 
1866     CommandMediaData* pMediaData = rEvent.GetMediaData();
1867     pMediaData->SetPassThroughToOS(false);
1868     switch (pMediaData->GetMediaId())
1869     {
1870 #if defined( MACOSX )
1871     case MediaCommand::Menu:
1872         if( !mnContextMenuEvent )
1873         {
1874         if( mpShowWindow )
1875             maPopupMousePos = mpShowWindow->GetPointerState().maPos;
1876         mnContextMenuEvent = Application::PostUserEvent( LINK( this, SlideshowImpl, ContextMenuHdl ) );
1877         }
1878         break;
1879     case MediaCommand::VolumeDown:
1880         gotoPreviousSlide();
1881         break;
1882     case MediaCommand::VolumeUp:
1883         gotoNextEffect();
1884         break;
1885 #endif
1886     case MediaCommand::NextTrack:
1887         gotoNextEffect();
1888         break;
1889     case MediaCommand::Pause:
1890         if( !mbIsPaused )
1891             blankScreen(0);
1892         break;
1893     case MediaCommand::Play:
1894         if( mbIsPaused )
1895             resume();
1896         break;
1897 
1898     case MediaCommand::PlayPause:
1899         if( mbIsPaused )
1900             resume();
1901         else
1902             blankScreen(0);
1903         break;
1904     case MediaCommand::PreviousTrack:
1905         gotoPreviousSlide();
1906         break;
1907     case MediaCommand::NextTrackHold:
1908         gotoLastSlide();
1909         break;
1910 
1911     case MediaCommand::Rewind:
1912         gotoFirstSlide();
1913         break;
1914     case MediaCommand::Stop:
1915         // in case the user cancels the presentation, switch to current slide
1916         // in edit mode
1917         if( mpSlideController && (ANIMATIONMODE_SHOW == meAnimationMode) )
1918         {
1919             if( mpSlideController->getCurrentSlideNumber() != -1 )
1920                 mnRestoreSlide = mpSlideController->getCurrentSlideNumber();
1921         }
1922         endPresentation();
1923         break;
1924     default:
1925         pMediaData->SetPassThroughToOS(true);
1926         break;
1927     }
1928 }
1929 
mouseButtonUp(const MouseEvent & rMEvt)1930 void SlideshowImpl::mouseButtonUp(const MouseEvent& rMEvt)
1931 {
1932     if( rMEvt.IsRight() && !mnContextMenuEvent )
1933     {
1934         maPopupMousePos = rMEvt.GetPosPixel();
1935         mnContextMenuEvent = Application::PostUserEvent( LINK( this, SlideshowImpl, ContextMenuHdl ) );
1936     }
1937 }
1938 
IMPL_LINK_NOARG(SlideshowImpl,ContextMenuHdl,void *,void)1939 IMPL_LINK_NOARG(SlideshowImpl, ContextMenuHdl, void*, void)
1940 {
1941     mnContextMenuEvent = nullptr;
1942 
1943     if (mpSlideController == nullptr)
1944         return;
1945 
1946     mbWasPaused = mbIsPaused;
1947     if( !mbWasPaused )
1948         pause();
1949 
1950     std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(nullptr, "modules/simpress/ui/slidecontextmenu.ui"));
1951     std::unique_ptr<weld::Menu> xMenu(xBuilder->weld_menu("menu"));
1952     OUString sNextImage(BMP_MENU_NEXT), sPrevImage(BMP_MENU_PREV);
1953     xMenu->insert(0, "next", SdResId(RID_SVXSTR_MENU_NEXT), &sNextImage, nullptr, nullptr, TRISTATE_INDET);
1954     xMenu->insert(1, "prev", SdResId(RID_SVXSTR_MENU_PREV), &sPrevImage, nullptr, nullptr, TRISTATE_INDET);
1955 
1956     // Adding button to display if in Pen  mode
1957     xMenu->set_active("pen", mbUsePen);
1958 
1959     const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode();
1960     xMenu->set_visible("next", mpSlideController->getNextSlideIndex() != -1);
1961     xMenu->set_visible("prev", (mpSlideController->getPreviousSlideIndex() != -1 ) || (eMode == SHOWWINDOWMODE_END) || (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK));
1962     xMenu->set_visible("edit", mpViewShell->GetDoc()->IsStartWithPresentation());
1963 
1964     std::unique_ptr<weld::Menu> xPageMenu(xBuilder->weld_menu("gotomenu"));
1965     OUString sFirstImage(BMP_MENU_FIRST), sLastImage(BMP_MENU_LAST);
1966     xPageMenu->insert(0, "first", SdResId(RID_SVXSTR_MENU_FIRST), &sFirstImage, nullptr, nullptr, TRISTATE_INDET);
1967     xPageMenu->insert(1, "last", SdResId(RID_SVXSTR_MENU_LAST), &sLastImage, nullptr, nullptr, TRISTATE_INDET);
1968 
1969     // populate slide goto list
1970     const sal_Int32 nPageNumberCount = mpSlideController->getSlideNumberCount();
1971     if( nPageNumberCount <= 1 )
1972     {
1973         xMenu->set_visible("goto", false);
1974     }
1975     else
1976     {
1977         sal_Int32 nCurrentSlideNumber = mpSlideController->getCurrentSlideNumber();
1978         if( (eMode == SHOWWINDOWMODE_END) || (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) )
1979             nCurrentSlideNumber = -1;
1980 
1981         xPageMenu->set_visible("first", mpSlideController->getSlideNumber(0) != nCurrentSlideNumber);
1982         xPageMenu->set_visible("last", mpSlideController->getSlideNumber(mpSlideController->getSlideIndexCount() - 1) != nCurrentSlideNumber);
1983 
1984         sal_Int32 nPageNumber;
1985 
1986         for( nPageNumber = 0; nPageNumber < nPageNumberCount; nPageNumber++ )
1987         {
1988             if( mpSlideController->isVisibleSlideNumber( nPageNumber ) )
1989             {
1990                 SdPage* pPage = mpDoc->GetSdPage(static_cast<sal_uInt16>(nPageNumber), PageKind::Standard);
1991                 if (pPage)
1992                 {
1993                     OUString sId(OUString::number(CM_SLIDES + nPageNumber));
1994                     xPageMenu->append_check(sId, pPage->GetName());
1995                     if (nPageNumber == nCurrentSlideNumber)
1996                         xPageMenu->set_active(sId.toUtf8(), true);
1997                 }
1998             }
1999         }
2000     }
2001 
2002     std::unique_ptr<weld::Menu> xBlankMenu(xBuilder->weld_menu("screenmenu"));
2003 
2004     if (mpShowWindow->GetShowWindowMode() == SHOWWINDOWMODE_BLANK)
2005     {
2006         xBlankMenu->set_active((mpShowWindow->GetBlankColor() == COL_WHITE) ? "white" : "black", true);
2007     }
2008 
2009     std::unique_ptr<weld::Menu> xWidthMenu(xBuilder->weld_menu("widthmenu"));
2010 
2011     // populate color width list
2012     sal_Int32 nIterator;
2013     double nWidth;
2014 
2015     nWidth = 4.0;
2016     for( nIterator = 1; nIterator < 6; nIterator++)
2017     {
2018         switch(nIterator)
2019         {
2020             case 1:
2021                 nWidth = 4.0;
2022                 break;
2023             case 2:
2024                 nWidth = 100.0;
2025                 break;
2026             case 3:
2027                 nWidth = 150.0;
2028                 break;
2029             case 4:
2030                 nWidth = 200.0;
2031                 break;
2032             case 5:
2033                 nWidth = 400.0;
2034                 break;
2035             default:
2036                 break;
2037         }
2038 
2039         if (nWidth == mdUserPaintStrokeWidth)
2040             xWidthMenu->set_active(OString::number(nWidth), true);
2041     }
2042 
2043     ::tools::Rectangle aRect(maPopupMousePos, Size(1,1));
2044     weld::Window* pParent = weld::GetPopupParent(*mpShowWindow, aRect);
2045     ContextMenuSelectHdl(xMenu->popup_at_rect(pParent, aRect));
2046 
2047     if( mxView.is() )
2048         mxView->ignoreNextMouseReleased();
2049 
2050     if( !mbWasPaused )
2051         resume();
2052 }
2053 
ContextMenuSelectHdl(const OString & rMenuId)2054 void SlideshowImpl::ContextMenuSelectHdl(const OString& rMenuId)
2055 {
2056     if (rMenuId == "prev")
2057     {
2058         gotoPreviousSlide();
2059         mbWasPaused = false;
2060     }
2061     else if(rMenuId == "next")
2062     {
2063         gotoNextSlide();
2064         mbWasPaused = false;
2065     }
2066     else if (rMenuId == "first")
2067     {
2068         gotoFirstSlide();
2069         mbWasPaused = false;
2070     }
2071     else if (rMenuId == "last")
2072     {
2073         gotoLastSlide();
2074         mbWasPaused = false;
2075     }
2076     else if (rMenuId == "black" || rMenuId == "white")
2077     {
2078         const Color aBlankColor(rMenuId == "white" ? COL_WHITE : COL_BLACK);
2079         if( mbWasPaused )
2080         {
2081             if( mpShowWindow->GetShowWindowMode() == SHOWWINDOWMODE_BLANK )
2082             {
2083                 if( mpShowWindow->GetBlankColor() == aBlankColor )
2084                 {
2085                     mbWasPaused = false;
2086                     mpShowWindow->RestartShow();
2087                     return;
2088                 }
2089             }
2090             mpShowWindow->RestartShow();
2091         }
2092         if( mpShowWindow->SetBlankMode( mpSlideController->getCurrentSlideIndex(), aBlankColor ) )
2093         {
2094             pause();
2095             mbWasPaused = true;
2096         }
2097     }
2098     else if (rMenuId == "color")
2099     {
2100         //Open a color picker based on SvColorDialog
2101         ::Color aColor( ColorTransparency, mnUserPaintColor );
2102         SvColorDialog aColorDlg;
2103         aColorDlg.SetColor( aColor );
2104 
2105         if (aColorDlg.Execute(mpShowWindow->GetFrameWeld()))
2106         {
2107             aColor = aColorDlg.GetColor();
2108             setPenColor(sal_Int32(aColor));
2109         }
2110         mbWasPaused = false;
2111     }
2112     else if (rMenuId == "4")
2113     {
2114         setPenWidth(4.0);
2115         mbWasPaused = false;
2116     }
2117     else if (rMenuId == "100")
2118     {
2119         setPenWidth(100.0);
2120         mbWasPaused = false;
2121     }
2122     else if (rMenuId == "150")
2123     {
2124         setPenWidth(150.0);
2125         mbWasPaused = false;
2126     }
2127     else if (rMenuId == "200")
2128     {
2129         setPenWidth(200.0);
2130         mbWasPaused = false;
2131     }
2132     else if (rMenuId == "400")
2133     {
2134         setPenWidth(400.0);
2135         mbWasPaused = false;
2136     }
2137     else if (rMenuId == "erase")
2138     {
2139         setEraseAllInk(true);
2140         mbWasPaused = false;
2141     }
2142     else if (rMenuId == "pen")
2143     {
2144         setUsePen(!mbUsePen);
2145         mbWasPaused = false;
2146     }
2147     else if (rMenuId == "edit")
2148     {
2149         // When in autoplay mode (pps/ppsx), offer editing of the presentation
2150         // Turn autostart off, else Impress will close when exiting the Presentation
2151         mpViewShell->GetDoc()->SetExitAfterPresenting(false);
2152         if( mpSlideController && (ANIMATIONMODE_SHOW == meAnimationMode) )
2153         {
2154             if( mpSlideController->getCurrentSlideNumber() != -1 )
2155             {
2156                 mnRestoreSlide = mpSlideController->getCurrentSlideNumber();
2157             }
2158         }
2159         endPresentation();
2160     }
2161     else if (rMenuId == "end")
2162     {
2163         // in case the user cancels the presentation, switch to current slide
2164         // in edit mode
2165         if( mpSlideController && (ANIMATIONMODE_SHOW == meAnimationMode) )
2166         {
2167             if( mpSlideController->getCurrentSlideNumber() != -1 )
2168             {
2169                 mnRestoreSlide = mpSlideController->getCurrentSlideNumber();
2170             }
2171         }
2172         endPresentation();
2173     }
2174     else if (!rMenuId.isEmpty())
2175     {
2176         sal_Int32 nPageNumber = rMenuId.toInt32() - CM_SLIDES;
2177         const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode();
2178         if( (eMode == SHOWWINDOWMODE_END) || (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) )
2179         {
2180             mpShowWindow->RestartShow( nPageNumber );
2181         }
2182         else if( nPageNumber != mpSlideController->getCurrentSlideNumber() )
2183         {
2184             displaySlideNumber( nPageNumber );
2185         }
2186         mbWasPaused = false;
2187     }
2188 }
2189 
createSlideShow()2190 Reference< XSlideShow > SlideshowImpl::createSlideShow()
2191 {
2192     Reference< XSlideShow > xShow;
2193 
2194     try
2195     {
2196         Reference< uno::XComponentContext > xContext =
2197             ::comphelper::getProcessComponentContext();
2198 
2199         xShow.set( presentation::SlideShow::create(xContext), UNO_SET_THROW );
2200     }
2201     catch( uno::Exception& )
2202     {
2203         TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::createSlideShow()" );
2204     }
2205 
2206     return xShow;
2207 }
2208 
createSlideList(bool bAll,std::u16string_view rPresSlide)2209 void SlideshowImpl::createSlideList( bool bAll, std::u16string_view rPresSlide )
2210 {
2211     const sal_uInt16 nSlideCount = mpDoc->GetSdPageCount( PageKind::Standard );
2212 
2213     if( !nSlideCount )
2214         return;
2215 
2216     SdCustomShow*   pCustomShow;
2217 
2218     if( mpDoc->GetCustomShowList() && maPresSettings.mbCustomShow )
2219         pCustomShow = mpDoc->GetCustomShowList()->GetCurObject();
2220     else
2221         pCustomShow = nullptr;
2222 
2223     // create animation slide controller
2224     AnimationSlideController::Mode eMode =
2225         ( pCustomShow && !pCustomShow->PagesVector().empty() ) ? AnimationSlideController::CUSTOM :
2226             (bAll ? AnimationSlideController::ALL : AnimationSlideController::FROM);
2227 
2228     Reference< XDrawPagesSupplier > xDrawPages( mpDoc->getUnoModel(), UNO_QUERY_THROW );
2229     Reference< XIndexAccess > xSlides( xDrawPages->getDrawPages(), UNO_QUERY_THROW );
2230     mpSlideController = std::make_shared<AnimationSlideController>( xSlides, eMode );
2231 
2232     if( eMode != AnimationSlideController::CUSTOM )
2233     {
2234         sal_Int32 nFirstVisibleSlide = 0;
2235 
2236         // normal presentation
2237         if( !rPresSlide.empty() )
2238         {
2239             sal_Int32 nSlide;
2240             bool bTakeNextAvailable = false;
2241 
2242             for( nSlide = 0, nFirstVisibleSlide = -1;
2243                 ( nSlide < nSlideCount ) && ( -1 == nFirstVisibleSlide ); nSlide++ )
2244             {
2245                 SdPage* pTestSlide = mpDoc->GetSdPage( static_cast<sal_uInt16>(nSlide), PageKind::Standard );
2246 
2247                 if( pTestSlide->GetName() == rPresSlide )
2248                 {
2249                     if( pTestSlide->IsExcluded() )
2250                         bTakeNextAvailable = true;
2251                     else
2252                         nFirstVisibleSlide = nSlide;
2253                 }
2254                 else if( bTakeNextAvailable && !pTestSlide->IsExcluded() )
2255                     nFirstVisibleSlide = nSlide;
2256             }
2257 
2258             if( -1 == nFirstVisibleSlide )
2259                 nFirstVisibleSlide = 0;
2260         }
2261 
2262         for( sal_Int32 i = 0; i < nSlideCount; i++ )
2263         {
2264             bool bVisible = ! mpDoc->GetSdPage( static_cast<sal_uInt16>(i), PageKind::Standard )->IsExcluded();
2265             if( bVisible || (eMode == AnimationSlideController::ALL) )
2266                 mpSlideController->insertSlideNumber( i, bVisible );
2267         }
2268 
2269         mpSlideController->setStartSlideNumber( nFirstVisibleSlide );
2270     }
2271     else
2272     {
2273         if( meAnimationMode != ANIMATIONMODE_SHOW && !rPresSlide.empty() )
2274         {
2275             sal_Int32 nSlide;
2276             for( nSlide = 0; nSlide < nSlideCount; nSlide++ )
2277                 if( rPresSlide == mpDoc->GetSdPage( static_cast<sal_uInt16>(nSlide), PageKind::Standard )->GetName() )
2278                     break;
2279 
2280             if( nSlide < nSlideCount )
2281                 mpSlideController->insertSlideNumber( static_cast<sal_uInt16>(nSlide) );
2282         }
2283 
2284         for( const auto& rpPage : pCustomShow->PagesVector() )
2285         {
2286             const sal_uInt16 nSdSlide = ( rpPage->GetPageNum() - 1 ) / 2;
2287 
2288             if( ! mpDoc->GetSdPage( nSdSlide, PageKind::Standard )->IsExcluded())
2289                 mpSlideController->insertSlideNumber( nSdSlide );
2290         }
2291     }
2292 }
2293 
2294 typedef sal_uInt16 (*FncGetChildWindowId)();
2295 
2296 const FncGetChildWindowId aShowChildren[] =
2297 {
2298     &AnimationChildWindow::GetChildWindowId,
2299     &Svx3DChildWindow::GetChildWindowId,
2300     &SvxFontWorkChildWindow::GetChildWindowId,
2301     &SvxColorChildWindow::GetChildWindowId,
2302     &SvxSearchDialogWrapper::GetChildWindowId,
2303     &SvxBmpMaskChildWindow::GetChildWindowId,
2304     &SvxIMapDlgChildWindow::GetChildWindowId,
2305     &SvxHlinkDlgWrapper::GetChildWindowId,
2306     &SfxInfoBarContainerChild::GetChildWindowId
2307 };
2308 
hideChildWindows()2309 void SlideshowImpl::hideChildWindows()
2310 {
2311     mnChildMask = 0;
2312 
2313     if( ANIMATIONMODE_SHOW != meAnimationMode )
2314         return;
2315 
2316     SfxViewFrame* pViewFrame = getViewFrame();
2317 
2318     if( !pViewFrame )
2319         return;
2320 
2321     for( sal_uLong i = 0; i < SAL_N_ELEMENTS( aShowChildren ); i++ )
2322     {
2323         const sal_uInt16 nId = ( *aShowChildren[ i ] )();
2324 
2325         if( pViewFrame->GetChildWindow( nId ) )
2326         {
2327             pViewFrame->SetChildWindow( nId, false );
2328             mnChildMask |= ::tools::ULong(1) << i;
2329         }
2330     }
2331 }
2332 
showChildWindows()2333 void SlideshowImpl::showChildWindows()
2334 {
2335     if( ANIMATIONMODE_SHOW == meAnimationMode )
2336     {
2337         SfxViewFrame* pViewFrame = getViewFrame();
2338         if( pViewFrame )
2339         {
2340             for( sal_uLong i = 0; i < SAL_N_ELEMENTS(aShowChildren); i++ )
2341             {
2342                 if( mnChildMask & ( ::tools::ULong(1) << i ) )
2343                     pViewFrame->SetChildWindow( ( *aShowChildren[ i ] )(), true );
2344             }
2345         }
2346     }
2347 }
2348 
getViewFrame() const2349 SfxViewFrame* SlideshowImpl::getViewFrame() const
2350 {
2351     return mpViewShell ? mpViewShell->GetViewFrame() : nullptr;
2352 }
2353 
getDispatcher() const2354 SfxDispatcher* SlideshowImpl::getDispatcher() const
2355 {
2356     return (mpViewShell && mpViewShell->GetViewFrame()) ? mpViewShell->GetViewFrame()->GetDispatcher() : nullptr;
2357 }
2358 
getBindings() const2359 SfxBindings* SlideshowImpl::getBindings() const
2360 {
2361     return (mpViewShell && mpViewShell->GetViewFrame()) ? &mpViewShell->GetViewFrame()->GetBindings() : nullptr;
2362 }
2363 
resize(const Size & rSize)2364 void SlideshowImpl::resize( const Size& rSize )
2365 {
2366     maPresSize = rSize;
2367 
2368     if(mpShowWindow)
2369     {
2370         mpShowWindow->SetSizePixel( maPresSize );
2371         mpShowWindow->Show();
2372     }
2373 
2374     if( mxView.is() ) try
2375     {
2376         awt::WindowEvent aEvt;
2377         mxView->windowResized(aEvt);
2378     }
2379     catch( Exception& )
2380     {
2381         TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::resize()" );
2382     }
2383 }
2384 
setActiveXToolbarsVisible(bool bVisible)2385 void SlideshowImpl::setActiveXToolbarsVisible( bool bVisible )
2386 {
2387     // in case of ActiveX control the toolbars should not be visible if slide show runs in window mode
2388     // actually it runs always in window mode in case of ActiveX control
2389     if ( !(!maPresSettings.mbFullScreen && mpDocSh && mpDocSh->GetMedium()) )
2390         return;
2391 
2392     const SfxBoolItem* pItem = SfxItemSet::GetItem<SfxBoolItem>(mpDocSh->GetMedium()->GetItemSet(), SID_VIEWONLY, false);
2393     if ( !(pItem && pItem->GetValue()) )
2394         return;
2395 
2396     // this is a plugin/activex mode, no toolbars should be visible during slide show
2397     // after the end of slide show they should be visible again
2398     SfxViewFrame* pViewFrame = getViewFrame();
2399     if( !pViewFrame )
2400         return;
2401 
2402     try
2403     {
2404         Reference< frame::XLayoutManager > xLayoutManager;
2405         Reference< beans::XPropertySet > xFrameProps( pViewFrame->GetFrame().GetFrameInterface(), UNO_QUERY_THROW );
2406         if ( ( xFrameProps->getPropertyValue( "LayoutManager" )
2407                     >>= xLayoutManager )
2408           && xLayoutManager.is() )
2409         {
2410             xLayoutManager->setVisible( bVisible );
2411         }
2412     }
2413     catch( uno::Exception& )
2414     {}
2415 }
2416 
activate()2417 void SAL_CALL SlideshowImpl::activate()
2418 {
2419     SolarMutexGuard aSolarGuard;
2420 
2421     maDeactivateTimer.Stop();
2422 
2423     if( mbActive || !mxShow.is() )
2424         return;
2425 
2426     mbActive = true;
2427 
2428     if( ANIMATIONMODE_SHOW == meAnimationMode )
2429     {
2430         if( mbAutoSaveWasOn )
2431             setAutoSaveState( false );
2432 
2433         if( mpShowWindow )
2434         {
2435             SfxViewFrame* pViewFrame = getViewFrame();
2436             SfxDispatcher* pDispatcher = pViewFrame ? pViewFrame->GetDispatcher() : nullptr;
2437 
2438             hideChildWindows();
2439 
2440             if( pDispatcher )
2441             {
2442                 // filter all forbidden slots
2443                 pDispatcher->SetSlotFilter( SfxSlotFilterState::ENABLED, pAllowed );
2444             }
2445 
2446             if( getBindings() )
2447                 getBindings()->InvalidateAll(true);
2448 
2449             mpShowWindow->GrabFocus();
2450         }
2451     }
2452 
2453     resume();
2454 }
2455 
deactivate()2456 void SAL_CALL SlideshowImpl::deactivate()
2457 {
2458     SolarMutexGuard aSolarGuard;
2459 
2460     if( mbActive && mxShow.is() )
2461     {
2462         maDeactivateTimer.Start();
2463     }
2464 }
2465 
IMPL_LINK_NOARG(SlideshowImpl,deactivateHdl,Timer *,void)2466 IMPL_LINK_NOARG(SlideshowImpl, deactivateHdl, Timer *, void)
2467 {
2468     if( !(mbActive && mxShow.is()) )
2469         return;
2470 
2471     mbActive = false;
2472 
2473     pause();
2474 
2475     if( ANIMATIONMODE_SHOW == meAnimationMode )
2476     {
2477         if( mbAutoSaveWasOn )
2478             setAutoSaveState( true );
2479 
2480         if( mpShowWindow )
2481         {
2482             showChildWindows();
2483         }
2484     }
2485 }
2486 
isActive()2487 sal_Bool SAL_CALL SlideshowImpl::isActive()
2488 {
2489     SolarMutexGuard aSolarGuard;
2490     return mbActive;
2491 }
2492 
setAutoSaveState(bool bOn)2493 void SlideshowImpl::setAutoSaveState( bool bOn)
2494 {
2495     try
2496     {
2497         uno::Reference<uno::XComponentContext> xContext( ::comphelper::getProcessComponentContext() );
2498 
2499         uno::Reference< util::XURLTransformer > xParser(util::URLTransformer::create(xContext));
2500         util::URL aURL;
2501         aURL.Complete = "vnd.sun.star.autorecovery:/setAutoSaveState";
2502         xParser->parseStrict(aURL);
2503 
2504         Sequence< beans::PropertyValue > aArgs(1);
2505         aArgs[0].Name = "AutoSaveState";
2506         aArgs[0].Value <<= bOn;
2507 
2508         uno::Reference< frame::XDispatch > xAutoSave = frame::theAutoRecovery::get(xContext);
2509         xAutoSave->dispatch(aURL, aArgs);
2510     }
2511     catch( Exception& )
2512     {
2513         TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::setAutoSaveState()");
2514     }
2515 }
2516 
getCurrentSlide()2517 Reference< XDrawPage > SAL_CALL SlideshowImpl::getCurrentSlide()
2518 {
2519     SolarMutexGuard aSolarGuard;
2520 
2521     Reference< XDrawPage > xSlide;
2522     if( mxShow.is() && mpSlideController )
2523     {
2524         sal_Int32 nSlide = getCurrentSlideNumber();
2525         if( (nSlide >= 0) && (nSlide < mpSlideController->getSlideNumberCount() ) )
2526             xSlide = mpSlideController->getSlideByNumber( nSlide );
2527     }
2528 
2529     return xSlide;
2530 }
2531 
getNextSlideIndex()2532 sal_Int32 SAL_CALL SlideshowImpl::getNextSlideIndex()
2533 {
2534     SolarMutexGuard aSolarGuard;
2535 
2536     if( mxShow.is() )
2537     {
2538         return mpSlideController->getNextSlideIndex();
2539     }
2540     else
2541     {
2542         return -1;
2543     }
2544 }
2545 
getCurrentSlideIndex()2546 sal_Int32 SAL_CALL SlideshowImpl::getCurrentSlideIndex()
2547 {
2548     return mpSlideController ? mpSlideController->getCurrentSlideIndex() : -1;
2549 }
2550 
2551 // css::presentation::XSlideShowController:
2552 
getSlideCount()2553 ::sal_Int32 SAL_CALL SlideshowImpl::getSlideCount()
2554 {
2555     return mpSlideController ? mpSlideController->getSlideIndexCount() : 0;
2556 }
2557 
getSlideByIndex(::sal_Int32 Index)2558 Reference< XDrawPage > SAL_CALL SlideshowImpl::getSlideByIndex(::sal_Int32 Index)
2559 {
2560     if ((mpSlideController == nullptr) || (Index < 0)
2561         || (Index >= mpSlideController->getSlideIndexCount()))
2562         throw IndexOutOfBoundsException();
2563 
2564     return mpSlideController->getSlideByNumber( mpSlideController->getSlideNumber( Index ) );
2565 }
2566 
getAlwaysOnTop()2567 sal_Bool SAL_CALL SlideshowImpl::getAlwaysOnTop()
2568 {
2569     SolarMutexGuard aSolarGuard;
2570     return maPresSettings.mbAlwaysOnTop;
2571 }
2572 
setAlwaysOnTop(sal_Bool bAlways)2573 void SAL_CALL SlideshowImpl::setAlwaysOnTop( sal_Bool bAlways )
2574 {
2575     SolarMutexGuard aSolarGuard;
2576     if( maPresSettings.mbAlwaysOnTop != bool(bAlways) )
2577     {
2578         maPresSettings.mbAlwaysOnTop = bAlways;
2579         // todo, can this be changed while running?
2580     }
2581 }
2582 
isFullScreen()2583 sal_Bool SAL_CALL SlideshowImpl::isFullScreen()
2584 {
2585     SolarMutexGuard aSolarGuard;
2586     return maPresSettings.mbFullScreen;
2587 }
2588 
getMouseVisible()2589 sal_Bool SAL_CALL SlideshowImpl::getMouseVisible()
2590 {
2591     SolarMutexGuard aSolarGuard;
2592     return maPresSettings.mbMouseVisible;
2593 }
2594 
setMouseVisible(sal_Bool bVisible)2595 void SAL_CALL SlideshowImpl::setMouseVisible( sal_Bool bVisible )
2596 {
2597     SolarMutexGuard aSolarGuard;
2598     if( maPresSettings.mbMouseVisible != bool(bVisible) )
2599     {
2600         maPresSettings.mbMouseVisible = bVisible;
2601         if( mpShowWindow )
2602             mpShowWindow->SetMouseAutoHide( !maPresSettings.mbMouseVisible );
2603     }
2604 }
2605 
getUsePen()2606 sal_Bool SAL_CALL SlideshowImpl::getUsePen()
2607 {
2608     SolarMutexGuard aSolarGuard;
2609     return mbUsePen;
2610 }
2611 
setUsePen(sal_Bool bMouseAsPen)2612 void SAL_CALL SlideshowImpl::setUsePen( sal_Bool bMouseAsPen )
2613 {
2614     SolarMutexGuard aSolarGuard;
2615     mbUsePen = bMouseAsPen;
2616     if( !mxShow.is() )
2617         return;
2618 
2619     try
2620     {
2621         // For Pencolor;
2622         Any aValue;
2623         if( mbUsePen )
2624             aValue <<= mnUserPaintColor;
2625         beans::PropertyValue aPenProp;
2626         aPenProp.Name = "UserPaintColor";
2627         aPenProp.Value = aValue;
2628         mxShow->setProperty( aPenProp );
2629 
2630         //for StrokeWidth :
2631         if( mbUsePen )
2632         {
2633             beans::PropertyValue aPenPropWidth;
2634             aPenPropWidth.Name = "UserPaintStrokeWidth";
2635             aPenPropWidth.Value <<= mdUserPaintStrokeWidth;
2636             mxShow->setProperty( aPenPropWidth );
2637 
2638             // for Pen Mode
2639             beans::PropertyValue aPenPropSwitchPenMode;
2640             aPenPropSwitchPenMode.Name = "SwitchPenMode";
2641             aPenPropSwitchPenMode.Value <<= true;
2642             mxShow->setProperty( aPenPropSwitchPenMode );
2643         }
2644     }
2645     catch( Exception& )
2646     {
2647         TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::setUsePen()" );
2648     }
2649 }
2650 
getPenWidth()2651 double SAL_CALL SlideshowImpl::getPenWidth()
2652 {
2653     SolarMutexGuard aSolarGuard;
2654     return mdUserPaintStrokeWidth;
2655 }
2656 
setPenWidth(double dStrokeWidth)2657 void SAL_CALL SlideshowImpl::setPenWidth( double dStrokeWidth )
2658 {
2659     SolarMutexGuard aSolarGuard;
2660     mdUserPaintStrokeWidth = dStrokeWidth;
2661     setUsePen( true ); // enable pen mode, update color and width
2662 }
2663 
getPenColor()2664 sal_Int32 SAL_CALL SlideshowImpl::getPenColor()
2665 {
2666     SolarMutexGuard aSolarGuard;
2667     return mnUserPaintColor;
2668 }
2669 
setPenColor(sal_Int32 nColor)2670 void SAL_CALL SlideshowImpl::setPenColor( sal_Int32 nColor )
2671 {
2672     SolarMutexGuard aSolarGuard;
2673     mnUserPaintColor = nColor;
2674     setUsePen( true ); // enable pen mode, update color
2675 }
2676 
setEraseAllInk(sal_Bool bEraseAllInk)2677 void SAL_CALL SlideshowImpl::setEraseAllInk(sal_Bool bEraseAllInk)
2678 {
2679     if( !bEraseAllInk )
2680         return;
2681 
2682     SolarMutexGuard aSolarGuard;
2683     if( !mxShow.is() )
2684         return;
2685 
2686     try
2687     {
2688         beans::PropertyValue aPenPropEraseAllInk;
2689         aPenPropEraseAllInk.Name = "EraseAllInk";
2690         aPenPropEraseAllInk.Value <<= bEraseAllInk;
2691         mxShow->setProperty( aPenPropEraseAllInk );
2692     }
2693     catch( Exception& )
2694     {
2695         TOOLS_WARN_EXCEPTION( "sd.slideshow", "sd::SlideshowImpl::setEraseAllInk()" );
2696     }
2697 }
2698 
2699 // XSlideShowController Methods
isRunning()2700 sal_Bool SAL_CALL SlideshowImpl::isRunning(  )
2701 {
2702     SolarMutexGuard aSolarGuard;
2703     return mxShow.is();
2704 }
2705 
gotoNextEffect()2706 void SAL_CALL SlideshowImpl::gotoNextEffect(  )
2707 {
2708     SolarMutexGuard aSolarGuard;
2709 
2710     if( !(mxShow.is() && mpSlideController && mpShowWindow) )
2711         return;
2712 
2713     if( mbIsPaused )
2714         resume();
2715 
2716     const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode();
2717     if( eMode == SHOWWINDOWMODE_END )
2718     {
2719         endPresentation();
2720     }
2721     else if( (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) )
2722     {
2723         mpShowWindow->RestartShow();
2724     }
2725     else
2726     {
2727         mxShow->nextEffect();
2728         update();
2729     }
2730 }
2731 
gotoPreviousEffect()2732 void SAL_CALL SlideshowImpl::gotoPreviousEffect(  )
2733 {
2734     SolarMutexGuard aSolarGuard;
2735 
2736     if( !(mxShow.is() && mpSlideController && mpShowWindow) )
2737         return;
2738 
2739     if( mbIsPaused )
2740         resume();
2741 
2742     const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode();
2743     if( (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) )
2744     {
2745         mpShowWindow->RestartShow();
2746     }
2747     else
2748     {
2749         mxShow->previousEffect();
2750         update();
2751     }
2752 }
2753 
gotoFirstSlide()2754 void SAL_CALL SlideshowImpl::gotoFirstSlide(  )
2755 {
2756     SolarMutexGuard aSolarGuard;
2757 
2758     if( !(mpShowWindow && mpSlideController) )
2759         return;
2760 
2761     if( mbIsPaused )
2762         resume();
2763 
2764     if( mpShowWindow->GetShowWindowMode() == SHOWWINDOWMODE_END )
2765     {
2766         if( mpSlideController->getSlideIndexCount() )
2767             mpShowWindow->RestartShow( 0);
2768     }
2769     else
2770     {
2771         displaySlideIndex( 0 );
2772     }
2773 }
2774 
gotoNextSlide()2775 void SAL_CALL SlideshowImpl::gotoNextSlide(  )
2776 {
2777     SolarMutexGuard aSolarGuard;
2778 
2779     if( mbIsPaused )
2780         resume();
2781 
2782     const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode();
2783     if( (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) )
2784     {
2785         mpShowWindow->RestartShow();
2786     }
2787     else
2788     {
2789         // if this is a show, ignore user inputs and
2790         // start 20ms timer to reenable inputs to filter
2791         // buffered inputs during slide transition
2792         if( meAnimationMode == ANIMATIONMODE_SHOW )
2793         {
2794             mbInputFreeze = true;
2795             maInputFreezeTimer.Start();
2796         }
2797 
2798         if( mpSlideController )
2799         {
2800             if( mpSlideController->nextSlide() )
2801             {
2802                 displayCurrentSlide();
2803             }
2804             else
2805             {
2806                 stopSound();
2807 
2808                 if( meAnimationMode == ANIMATIONMODE_PREVIEW )
2809                 {
2810                     endPresentation();
2811                 }
2812                 else if( maPresSettings.mbEndless )
2813                 {
2814                     if( maPresSettings.mnPauseTimeout )
2815                     {
2816                         if( mpShowWindow )
2817                         {
2818                             if ( maPresSettings.mbShowPauseLogo )
2819                             {
2820                                 Graphic aGraphic(SfxApplication::GetApplicationLogo(360));
2821                                 mpShowWindow->SetPauseMode( maPresSettings.mnPauseTimeout, &aGraphic );
2822                             }
2823                             else
2824                                 mpShowWindow->SetPauseMode( maPresSettings.mnPauseTimeout );
2825                         }
2826                     }
2827                     else
2828                     {
2829                         displaySlideIndex( 0 );
2830                     }
2831                 }
2832                 else
2833                 {
2834                     if( mpShowWindow )
2835                     {
2836                         mpShowWindow->SetEndMode();
2837                         if( !mpViewShell->GetDoc()->IsStartWithPresentation() )
2838                             pause();
2839                     }
2840                 }
2841             }
2842         }
2843     }
2844 }
2845 
gotoPreviousSlide()2846 void SAL_CALL SlideshowImpl::gotoPreviousSlide(  )
2847 {
2848     gotoPreviousSlide(false);
2849 }
2850 
gotoPreviousSlide(const bool bSkipAllMainSequenceEffects)2851 void SlideshowImpl::gotoPreviousSlide (const bool bSkipAllMainSequenceEffects)
2852 {
2853     SolarMutexGuard aSolarGuard;
2854 
2855     if( !(mxShow.is() && mpSlideController) )
2856         return;
2857 
2858     try
2859     {
2860         if( mbIsPaused )
2861             resume();
2862 
2863         const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode();
2864         if( eMode == SHOWWINDOWMODE_END )
2865         {
2866             mpShowWindow->RestartShow( mpSlideController->getCurrentSlideIndex() );
2867         }
2868         else if( (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) )
2869         {
2870             mpShowWindow->RestartShow();
2871         }
2872         else
2873         {
2874             if( mpSlideController->previousSlide())
2875                 displayCurrentSlide(bSkipAllMainSequenceEffects);
2876             else if (bSkipAllMainSequenceEffects)
2877             {
2878                 // We could not go to the previous slide (probably because
2879                 // the current slide is already the first one).  We still
2880                 // have to call displayCurrentSlide because the calling
2881                 // slideshow can not determine whether there is a previous
2882                 // slide or not and has already prepared for a slide change.
2883                 // This slide change has to be completed now, even when
2884                 // changing to the same slide.
2885                 // Note that in this special case we do NOT pass
2886                 // bSkipAllMainSequenceEffects because we display the same
2887                 // slide as before and do not want to show all its effects.
2888                 displayCurrentSlide();
2889             }
2890         }
2891     }
2892     catch( Exception& )
2893     {
2894         TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::gotoPreviousSlide()" );
2895     }
2896 }
2897 
gotoLastSlide()2898 void SAL_CALL SlideshowImpl::gotoLastSlide()
2899 {
2900     SolarMutexGuard aSolarGuard;
2901 
2902     if( !mpSlideController )
2903         return;
2904 
2905     if( mbIsPaused )
2906         resume();
2907 
2908     const sal_Int32 nLastSlideIndex = mpSlideController->getSlideIndexCount() - 1;
2909     if( nLastSlideIndex >= 0 )
2910     {
2911         if( mpShowWindow->GetShowWindowMode() == SHOWWINDOWMODE_END )
2912         {
2913             mpShowWindow->RestartShow( nLastSlideIndex );
2914         }
2915         else
2916         {
2917             displaySlideIndex( nLastSlideIndex );
2918         }
2919     }
2920 }
2921 
gotoBookmark(const OUString & rBookmark)2922 void SAL_CALL SlideshowImpl::gotoBookmark( const OUString& rBookmark )
2923 {
2924     SolarMutexGuard aSolarGuard;
2925 
2926     if( mbIsPaused )
2927         resume();
2928 
2929     sal_Int32 nSlideNumber = getSlideNumberForBookmark( rBookmark );
2930     if( nSlideNumber != -1 )
2931         displaySlideNumber( nSlideNumber );
2932 }
2933 
gotoSlide(const Reference<XDrawPage> & xSlide)2934 void SAL_CALL SlideshowImpl::gotoSlide( const Reference< XDrawPage >& xSlide )
2935 {
2936     SolarMutexGuard aSolarGuard;
2937 
2938     if( !(mpSlideController && xSlide.is()) )
2939         return;
2940 
2941     if( mbIsPaused )
2942         resume();
2943 
2944     const sal_Int32 nSlideCount = mpSlideController->getSlideNumberCount();
2945     for( sal_Int32 nSlide = 0; nSlide < nSlideCount; nSlide++ )
2946     {
2947         if( mpSlideController->getSlideByNumber( nSlide ) == xSlide )
2948         {
2949             displaySlideNumber( nSlide );
2950         }
2951     }
2952 }
2953 
gotoSlideIndex(sal_Int32 nIndex)2954 void SAL_CALL SlideshowImpl::gotoSlideIndex( sal_Int32 nIndex )
2955 {
2956     SolarMutexGuard aSolarGuard;
2957 
2958     if( mbIsPaused )
2959         resume();
2960 
2961     displaySlideIndex( nIndex );
2962 }
2963 
stopSound()2964 void SAL_CALL SlideshowImpl::stopSound(  )
2965 {
2966     SolarMutexGuard aSolarGuard;
2967 
2968     try
2969     {
2970         if( mxPlayer.is() )
2971         {
2972             mxPlayer->stop();
2973             mxPlayer.clear();
2974         }
2975     }
2976     catch( Exception& )
2977     {
2978         TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::stopSound()" );
2979     }
2980 }
2981 
2982 // XIndexAccess
2983 
getCount()2984 ::sal_Int32 SAL_CALL SlideshowImpl::getCount(  )
2985 {
2986     return getSlideCount();
2987 }
2988 
getByIndex(::sal_Int32 Index)2989 css::uno::Any SAL_CALL SlideshowImpl::getByIndex( ::sal_Int32 Index )
2990 {
2991     return Any( getSlideByIndex( Index ) );
2992 }
2993 
getElementType()2994 css::uno::Type SAL_CALL SlideshowImpl::getElementType(  )
2995 {
2996     return cppu::UnoType<XDrawPage>::get();
2997 }
2998 
hasElements()2999 sal_Bool SAL_CALL SlideshowImpl::hasElements(  )
3000 {
3001     return getSlideCount() != 0;
3002 }
3003 
getSlideShow()3004 Reference< XSlideShow > SAL_CALL SlideshowImpl::getSlideShow()
3005 {
3006     return mxShow;
3007 }
3008 
PresentationSettingsEx(const PresentationSettingsEx & r)3009 PresentationSettingsEx::PresentationSettingsEx( const PresentationSettingsEx& r )
3010 : PresentationSettings( r )
3011 , mbRehearseTimings(r.mbRehearseTimings)
3012 , mbPreview(r.mbPreview)
3013 , mpParentWindow( nullptr )
3014 {
3015 }
3016 
PresentationSettingsEx(PresentationSettings const & r)3017 PresentationSettingsEx::PresentationSettingsEx( PresentationSettings const & r )
3018 : PresentationSettings( r )
3019 , mbRehearseTimings(false)
3020 , mbPreview(false)
3021 , mpParentWindow(nullptr)
3022 {
3023 }
3024 
SetArguments(const Sequence<PropertyValue> & rArguments)3025 void PresentationSettingsEx::SetArguments( const Sequence< PropertyValue >& rArguments )
3026 {
3027     for( const PropertyValue& rValue : rArguments )
3028     {
3029         SetPropertyValue( rValue.Name, rValue.Value );
3030     }
3031 }
3032 
SetPropertyValue(std::u16string_view rProperty,const Any & rValue)3033 void PresentationSettingsEx::SetPropertyValue( std::u16string_view rProperty, const Any& rValue )
3034 {
3035     if ( rProperty == u"RehearseTimings" )
3036     {
3037         if( rValue >>= mbRehearseTimings )
3038             return;
3039     }
3040     else if ( rProperty == u"Preview" )
3041     {
3042         if( rValue >>= mbPreview )
3043             return;
3044     }
3045     else if ( rProperty == u"AnimationNode" )
3046     {
3047         if( rValue >>= mxAnimationNode )
3048             return;
3049     }
3050     else if ( rProperty == u"ParentWindow" )
3051     {
3052         Reference< XWindow > xWindow;
3053         if( rValue >>= xWindow )
3054         {
3055             mpParentWindow = xWindow.is() ? VCLUnoHelper::GetWindow( xWindow )
3056                                           : nullptr;
3057             return;
3058         }
3059     }
3060     else if ( rProperty == u"AllowAnimations" )
3061     {
3062         if( rValue >>= mbAnimationAllowed )
3063             return;
3064     }
3065     else if ( rProperty == u"FirstPage" )
3066     {
3067         OUString aPresPage;
3068         if( rValue >>= aPresPage )
3069         {
3070             maPresPage = getUiNameFromPageApiNameImpl(aPresPage);
3071             mbCustomShow = false;
3072             mbAll = false;
3073             return;
3074         }
3075         else
3076         {
3077             if( rValue >>= mxStartPage )
3078                 return;
3079         }
3080     }
3081     else if ( rProperty == u"IsAlwaysOnTop" )
3082     {
3083         if( rValue >>= mbAlwaysOnTop )
3084             return;
3085     }
3086     else if ( rProperty == u"IsAutomatic" )
3087     {
3088         if( rValue >>= mbManual )
3089             return;
3090     }
3091     else if ( rProperty == u"IsEndless" )
3092     {
3093         if( rValue >>= mbEndless )
3094             return;
3095     }
3096     else if ( rProperty == u"IsFullScreen" )
3097     {
3098         if( rValue >>= mbFullScreen )
3099             return;
3100     }
3101     else if ( rProperty == u"IsMouseVisible" )
3102     {
3103         if( rValue >>= mbMouseVisible )
3104             return;
3105     }
3106     else if ( rProperty == u"Pause" )
3107     {
3108         sal_Int32 nPause = -1;
3109         if( (rValue >>= nPause) && (nPause >= 0) )
3110         {
3111             mnPauseTimeout = nPause;
3112             return;
3113         }
3114     }
3115     else if ( rProperty == u"UsePen" )
3116     {
3117         if( rValue >>= mbMouseAsPen )
3118             return;
3119     }
3120     throw IllegalArgumentException();
3121 }
3122 
3123 // XAnimationListener
3124 
SlideShowListenerProxy(const rtl::Reference<SlideshowImpl> & xController,const css::uno::Reference<css::presentation::XSlideShow> & xSlideShow)3125 SlideShowListenerProxy::SlideShowListenerProxy( const rtl::Reference< SlideshowImpl >& xController, const css::uno::Reference< css::presentation::XSlideShow >& xSlideShow )
3126 : maListeners( m_aMutex )
3127 , mxController( xController )
3128 , mxSlideShow( xSlideShow )
3129 {
3130 }
3131 
~SlideShowListenerProxy()3132 SlideShowListenerProxy::~SlideShowListenerProxy()
3133 {
3134 }
3135 
addAsSlideShowListener()3136 void SlideShowListenerProxy::addAsSlideShowListener()
3137 {
3138     if( mxSlideShow.is() )
3139     {
3140         Reference< XSlideShowListener > xSlideShowListener( this );
3141         mxSlideShow->addSlideShowListener( xSlideShowListener );
3142     }
3143 }
3144 
removeAsSlideShowListener()3145 void SlideShowListenerProxy::removeAsSlideShowListener()
3146 {
3147     if( mxSlideShow.is() )
3148     {
3149         Reference< XSlideShowListener > xSlideShowListener( this );
3150         mxSlideShow->removeSlideShowListener( xSlideShowListener );
3151     }
3152 }
3153 
addShapeEventListener(const css::uno::Reference<css::drawing::XShape> & xShape)3154 void SlideShowListenerProxy::addShapeEventListener( const css::uno::Reference< css::drawing::XShape >& xShape )
3155 {
3156     if( mxSlideShow.is() )
3157     {
3158         Reference< XShapeEventListener > xListener( this );
3159         mxSlideShow->addShapeEventListener( xListener, xShape );
3160     }
3161 }
3162 
removeShapeEventListener(const css::uno::Reference<css::drawing::XShape> & xShape)3163 void SlideShowListenerProxy::removeShapeEventListener( const css::uno::Reference< css::drawing::XShape >& xShape )
3164 {
3165     if( mxSlideShow.is() )
3166     {
3167         Reference< XShapeEventListener > xListener( this );
3168         mxSlideShow->removeShapeEventListener( xListener, xShape );
3169     }
3170 }
3171 
addSlideShowListener(const css::uno::Reference<css::presentation::XSlideShowListener> & xListener)3172 void SlideShowListenerProxy::addSlideShowListener( const css::uno::Reference< css::presentation::XSlideShowListener >& xListener )
3173 {
3174     maListeners.addInterface(xListener);
3175 }
3176 
removeSlideShowListener(const css::uno::Reference<css::presentation::XSlideShowListener> & xListener)3177 void SlideShowListenerProxy::removeSlideShowListener( const css::uno::Reference< css::presentation::XSlideShowListener >& xListener )
3178 {
3179     maListeners.removeInterface(xListener);
3180 }
3181 
beginEvent(const Reference<XAnimationNode> & xNode)3182 void SAL_CALL SlideShowListenerProxy::beginEvent( const Reference< XAnimationNode >& xNode )
3183 {
3184     ::osl::MutexGuard aGuard( m_aMutex );
3185 
3186     if( maListeners.getLength() >= 0 )
3187     {
3188         maListeners.forEach<XSlideShowListener>(
3189             [&] (Reference<XAnimationListener> const& xListener) {
3190                 return xListener->beginEvent(xNode);
3191             } );
3192     }
3193 }
3194 
endEvent(const Reference<XAnimationNode> & xNode)3195 void SAL_CALL SlideShowListenerProxy::endEvent( const Reference< XAnimationNode >& xNode )
3196 {
3197     ::osl::MutexGuard aGuard( m_aMutex );
3198 
3199     if( maListeners.getLength() >= 0 )
3200     {
3201         maListeners.forEach<XSlideShowListener>(
3202             [&] (Reference<XAnimationListener> const& xListener) {
3203                 return xListener->endEvent(xNode);
3204             } );
3205     }
3206 }
3207 
repeat(const Reference<XAnimationNode> & xNode,::sal_Int32 nRepeat)3208 void SAL_CALL SlideShowListenerProxy::repeat( const Reference< XAnimationNode >& xNode, ::sal_Int32 nRepeat )
3209 {
3210     ::osl::MutexGuard aGuard( m_aMutex );
3211 
3212     if( maListeners.getLength() >= 0 )
3213     {
3214         maListeners.forEach<XSlideShowListener>(
3215             [&] (Reference<XAnimationListener> const& xListener) {
3216                 return xListener->repeat(xNode, nRepeat);
3217             } );
3218     }
3219 }
3220 
3221 // css::presentation::XSlideShowListener:
3222 
paused()3223 void SAL_CALL SlideShowListenerProxy::paused(  )
3224 {
3225     ::osl::MutexGuard aGuard( m_aMutex );
3226 
3227     maListeners.forEach<XSlideShowListener>(
3228         [](uno::Reference<presentation::XSlideShowListener> const& xListener)
3229         {
3230             xListener->paused();
3231         });
3232 }
3233 
resumed()3234 void SAL_CALL SlideShowListenerProxy::resumed(  )
3235 {
3236     ::osl::MutexGuard aGuard( m_aMutex );
3237 
3238     maListeners.forEach<XSlideShowListener>(
3239         [](uno::Reference<presentation::XSlideShowListener> const& xListener)
3240         {
3241             xListener->resumed();
3242         });
3243 }
3244 
slideTransitionStarted()3245 void SAL_CALL SlideShowListenerProxy::slideTransitionStarted( )
3246 {
3247     ::osl::MutexGuard aGuard( m_aMutex );
3248 
3249     maListeners.forEach<XSlideShowListener>(
3250         [](uno::Reference<presentation::XSlideShowListener> const& xListener)
3251         {
3252             xListener->slideTransitionStarted();
3253         });
3254 }
3255 
slideTransitionEnded()3256 void SAL_CALL SlideShowListenerProxy::slideTransitionEnded( )
3257 {
3258     ::osl::MutexGuard aGuard( m_aMutex );
3259 
3260     maListeners.forEach<XSlideShowListener>(
3261         [](uno::Reference<presentation::XSlideShowListener> const& xListener)
3262         {
3263             xListener->slideTransitionEnded ();
3264         });
3265 }
3266 
slideAnimationsEnded()3267 void SAL_CALL SlideShowListenerProxy::slideAnimationsEnded(  )
3268 {
3269     ::osl::MutexGuard aGuard( m_aMutex );
3270 
3271     maListeners.forEach<XSlideShowListener>(
3272         [](uno::Reference<presentation::XSlideShowListener> const& xListener)
3273         {
3274             xListener->slideAnimationsEnded ();
3275         });
3276 }
3277 
slideEnded(sal_Bool bReverse)3278 void SlideShowListenerProxy::slideEnded(sal_Bool bReverse)
3279 {
3280     {
3281         ::osl::MutexGuard aGuard( m_aMutex );
3282 
3283         if( maListeners.getLength() >= 0 )
3284         {
3285             maListeners.forEach<XSlideShowListener>(
3286                 [&] (Reference<XSlideShowListener> const& xListener) {
3287                     return xListener->slideEnded(bReverse);
3288                 } );
3289         }
3290     }
3291 
3292     {
3293         SolarMutexGuard aSolarGuard;
3294         if( mxController.is() )
3295             mxController->slideEnded(bReverse);
3296     }
3297 }
3298 
hyperLinkClicked(OUString const & aHyperLink)3299 void SlideShowListenerProxy::hyperLinkClicked( OUString const& aHyperLink )
3300 {
3301     {
3302         ::osl::MutexGuard aGuard( m_aMutex );
3303 
3304         if( maListeners.getLength() >= 0 )
3305         {
3306             maListeners.forEach<XSlideShowListener>(
3307                 [&] (Reference<XSlideShowListener> const& xListener) {
3308                     return xListener->hyperLinkClicked(aHyperLink);
3309                 } );
3310         }
3311     }
3312 
3313     {
3314         SolarMutexGuard aSolarGuard;
3315         if( mxController.is() )
3316             mxController->hyperLinkClicked(aHyperLink);
3317     }
3318 }
3319 
3320 // XEventListener
3321 
disposing(const css::lang::EventObject & aDisposeEvent)3322 void SAL_CALL SlideShowListenerProxy::disposing( const css::lang::EventObject& aDisposeEvent )
3323 {
3324     maListeners.disposeAndClear( aDisposeEvent );
3325     mxController.clear();
3326     mxSlideShow.clear();
3327 }
3328 
3329 // XShapeEventListener
3330 
click(const Reference<XShape> & xShape,const css::awt::MouseEvent &)3331 void SAL_CALL SlideShowListenerProxy::click( const Reference< XShape >& xShape, const css::awt::MouseEvent& /*aOriginalEvent*/ )
3332 {
3333     SolarMutexGuard aSolarGuard;
3334     if( mxController.is() )
3335         mxController->click(xShape );
3336 }
3337 
3338 } // namespace ::sd
3339 
3340 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
3341