bump product version to 6.3.0.0.beta1
[LibreOffice.git] / sd / source / ui / slideshow / slideshowimpl.cxx
blobaf948c513548f047e88c4f72f24c39201bb93ccc
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <algorithm>
24 #include <config_features.h>
26 #include <com/sun/star/frame/theAutoRecovery.hpp>
27 #include <com/sun/star/lang/XInitialization.hpp>
28 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
29 #include <com/sun/star/document/XEventsSupplier.hpp>
30 #include <com/sun/star/drawing/XMasterPageTarget.hpp>
31 #include <com/sun/star/container/XNameReplace.hpp>
32 #include <com/sun/star/beans/PropertyValue.hpp>
33 #include <com/sun/star/beans/XPropertySetInfo.hpp>
34 #include <com/sun/star/beans/XPropertySet.hpp>
35 #include <com/sun/star/awt/SystemPointer.hpp>
36 #include <com/sun/star/util/URLTransformer.hpp>
37 #include <com/sun/star/util/XURLTransformer.hpp>
38 #include <com/sun/star/frame/XDispatch.hpp>
39 #include <com/sun/star/frame/XLayoutManager.hpp>
40 #include <com/sun/star/presentation/SlideShow.hpp>
41 #include <com/sun/star/media/XPlayer.hpp>
42 #include <svl/aeitem.hxx>
43 #include <svl/stritem.hxx>
44 #include <svl/urihelper.hxx>
45 #include <unotools/saveopt.hxx>
46 #include <basic/sbstar.hxx>
48 #include <toolkit/helper/vclunohelper.hxx>
49 #include <tools/diagnose_ex.h>
51 #include <sfx2/infobar.hxx>
52 #include <sfx2/request.hxx>
53 #include <sfx2/dispatch.hxx>
54 #include <sfx2/docfile.hxx>
55 #include <sfx2/app.hxx>
56 #include <sfx2/viewfrm.hxx>
57 #include <svx/unoapi.hxx>
58 #include <svx/svdoole2.hxx>
59 #include <sfx2/templdlg.hxx>
60 #include <svx/f3dchild.hxx>
61 #include <svx/imapdlg.hxx>
62 #include <svx/fontwork.hxx>
63 #include <svx/SvxColorChildWindow.hxx>
64 #include <svx/bmpmask.hxx>
65 #include <svx/srchdlg.hxx>
66 #include <svx/hyperdlg.hxx>
67 #include <svx/svxids.hrc>
68 #include <AnimationChildWindow.hxx>
69 #include <notifydocumentevent.hxx>
70 #include "slideshowimpl.hxx"
71 #include "slideshowviewimpl.hxx"
72 #include <pgjump.hxx>
73 #include "PaneHider.hxx"
75 #include <bitmaps.hlst>
76 #include <vcl/canvastools.hxx>
77 #include <vcl/commandevent.hxx>
78 #include <vcl/commandinfoprovider.hxx>
80 #include <vcl/settings.hxx>
81 #include <vcl/scheduler.hxx>
82 #include <vcl/svapp.hxx>
83 #include <vcl/help.hxx>
84 #include <comphelper/anytostring.hxx>
85 #include <comphelper/processfactory.hxx>
86 #include <cppuhelper/exc_hlp.hxx>
87 #include <rtl/ref.hxx>
88 #include <sal/log.hxx>
89 #include <canvas/elapsedtime.hxx>
90 #include <avmedia/mediawindow.hxx>
91 #include <svtools/colrdlg.hxx>
92 #include <DrawDocShell.hxx>
93 #include <ViewShellBase.hxx>
94 #include <PresentationViewShell.hxx>
95 #include <RemoteServer.hxx>
96 #include <customshowlist.hxx>
97 #include <unopage.hxx>
98 #include <sdpage.hxx>
99 #include <sdmod.hxx>
100 #include <app.hrc>
101 #include <cusshow.hxx>
102 #include <optsitem.hxx>
104 #define CM_SLIDES 21
106 using ::com::sun::star::animations::XAnimationNode;
107 using ::com::sun::star::animations::XAnimationListener;
108 using ::com::sun::star::awt::XWindow;
109 using namespace ::com::sun::star;
110 using namespace ::com::sun::star::lang;
111 using namespace ::com::sun::star::uno;
112 using namespace ::com::sun::star::drawing;
113 using namespace ::com::sun::star::container;
114 using namespace ::com::sun::star::document;
115 using namespace ::com::sun::star::presentation;
116 using namespace ::com::sun::star::beans;
118 namespace sd
120 /** Slots, which will be disabled in the slide show and are managed by Sfx.
121 Have to be sorted in the order of the SIDs */
122 static sal_uInt16 const pAllowed[] =
124 SID_OPENDOC , // 5501 ///< that internally jumps work
125 SID_JUMPTOMARK , // 5598
126 SID_OPENHYPERLINK , // 6676
127 SID_PRESENTATION_END // 27218
130 class AnimationSlideController
132 public:
133 enum Mode { ALL, FROM, CUSTOM, PREVIEW };
135 public:
136 AnimationSlideController( Reference< XIndexAccess > const & xSlides, Mode eMode );
138 void setStartSlideNumber( sal_Int32 nSlideNumber ) { mnStartSlideNumber = nSlideNumber; }
139 sal_Int32 getStartSlideIndex() const;
141 sal_Int32 getCurrentSlideNumber() const;
142 sal_Int32 getCurrentSlideIndex() const;
144 sal_Int32 getSlideIndexCount() const { return maSlideNumbers.size(); }
145 sal_Int32 getSlideNumberCount() const { return mnSlideCount; }
147 sal_Int32 getSlideNumber( sal_Int32 nSlideIndex ) const;
149 void insertSlideNumber( sal_Int32 nSlideNumber, bool bVisible = true );
150 void setPreviewNode( const Reference< XAnimationNode >& xPreviewNode );
152 bool jumpToSlideIndex( sal_Int32 nNewSlideIndex );
153 bool jumpToSlideNumber( sal_Int32 nNewSlideIndex );
155 bool nextSlide();
156 bool previousSlide();
158 void displayCurrentSlide( const Reference< XSlideShow >& xShow,
159 const Reference< XDrawPagesSupplier>& xDrawPages,
160 const bool bSkipAllMainSequenceEffects );
162 sal_Int32 getNextSlideIndex() const;
163 sal_Int32 getPreviousSlideIndex() const;
165 bool isVisibleSlideNumber( sal_Int32 nSlideNumber ) const;
167 Reference< XDrawPage > getSlideByNumber( sal_Int32 nSlideNumber ) const;
169 sal_Int32 getNextSlideNumber() const;
171 bool hasSlides() const { return !maSlideNumbers.empty(); }
173 private:
174 bool getSlideAPI( sal_Int32 nSlideNumber, Reference< XDrawPage >& xSlide, Reference< XAnimationNode >& xAnimNode );
175 sal_Int32 findSlideIndex( sal_Int32 nSlideNumber ) const;
177 bool isValidIndex( sal_Int32 nIndex ) const { return (nIndex >= 0) && (nIndex < static_cast<sal_Int32>(maSlideNumbers.size())); }
178 bool isValidSlideNumber( sal_Int32 nSlideNumber ) const { return (nSlideNumber >= 0) && (nSlideNumber < mnSlideCount); }
180 private:
181 Mode const meMode;
182 sal_Int32 mnStartSlideNumber;
183 std::vector< sal_Int32 > maSlideNumbers;
184 std::vector< bool > maSlideVisible;
185 std::vector< bool > maSlideVisited;
186 Reference< XAnimationNode > mxPreviewNode;
187 sal_Int32 mnSlideCount;
188 sal_Int32 mnCurrentSlideIndex;
189 sal_Int32 mnHiddenSlideNumber;
190 Reference< XIndexAccess > mxSlides;
193 Reference< XDrawPage > AnimationSlideController::getSlideByNumber( sal_Int32 nSlideNumber ) const
195 Reference< XDrawPage > xSlide;
196 if( mxSlides.is() && (nSlideNumber >= 0) && (nSlideNumber < mxSlides->getCount()) )
197 mxSlides->getByIndex( nSlideNumber ) >>= xSlide;
198 return xSlide;
201 bool AnimationSlideController::isVisibleSlideNumber( sal_Int32 nSlideNumber ) const
203 sal_Int32 nIndex = findSlideIndex( nSlideNumber );
205 if( nIndex != -1 )
206 return maSlideVisible[ nIndex ];
207 else
208 return false;
211 void AnimationSlideController::setPreviewNode( const Reference< XAnimationNode >& xPreviewNode )
213 mxPreviewNode = xPreviewNode;
216 AnimationSlideController::AnimationSlideController( Reference< XIndexAccess > const & xSlides, Mode eMode )
217 : meMode( eMode )
218 , mnStartSlideNumber(-1)
219 , mnSlideCount( 0 )
220 , mnCurrentSlideIndex(0)
221 , mnHiddenSlideNumber( -1 )
222 , mxSlides( xSlides )
224 if( mxSlides.is() )
225 mnSlideCount = xSlides->getCount();
228 sal_Int32 AnimationSlideController::getStartSlideIndex() const
230 if( mnStartSlideNumber >= 0 )
232 sal_Int32 nIndex;
233 const sal_Int32 nCount = maSlideNumbers.size();
235 for( nIndex = 0; nIndex < nCount; nIndex++ )
237 if( maSlideNumbers[nIndex] == mnStartSlideNumber )
238 return nIndex;
242 return 0;
245 sal_Int32 AnimationSlideController::getCurrentSlideNumber() const
247 if( mnHiddenSlideNumber != -1 )
248 return mnHiddenSlideNumber;
249 else if( !maSlideNumbers.empty() )
250 return maSlideNumbers[mnCurrentSlideIndex];
251 else
252 return 0;
255 sal_Int32 AnimationSlideController::getCurrentSlideIndex() const
257 if( mnHiddenSlideNumber != -1 )
258 return -1;
259 else
260 return mnCurrentSlideIndex;
263 bool AnimationSlideController::jumpToSlideIndex( sal_Int32 nNewSlideIndex )
265 if( isValidIndex( nNewSlideIndex ) )
267 mnCurrentSlideIndex = nNewSlideIndex;
268 mnHiddenSlideNumber = -1;
269 maSlideVisited[mnCurrentSlideIndex] = true;
270 return true;
272 else
274 return false;
278 bool AnimationSlideController::jumpToSlideNumber( sal_Int32 nNewSlideNumber )
280 sal_Int32 nIndex = findSlideIndex( nNewSlideNumber );
281 if( isValidIndex( nIndex ) )
283 return jumpToSlideIndex( nIndex );
285 else if( (nNewSlideNumber >= 0) && (nNewSlideNumber < mnSlideCount) )
287 // jump to a hidden slide
288 mnHiddenSlideNumber = nNewSlideNumber;
289 return true;
291 else
293 return false;
297 sal_Int32 AnimationSlideController::getSlideNumber( sal_Int32 nSlideIndex ) const
299 if( isValidIndex( nSlideIndex ) )
300 return maSlideNumbers[nSlideIndex];
301 else
302 return -1;
305 void AnimationSlideController::insertSlideNumber( sal_Int32 nSlideNumber, bool bVisible /* = true */ )
307 DBG_ASSERT( isValidSlideNumber( nSlideNumber ), "sd::AnimationSlideController::insertSlideNumber(), illegal index" );
308 if( isValidSlideNumber( nSlideNumber ) )
310 maSlideNumbers.push_back( nSlideNumber );
311 maSlideVisible.push_back( bVisible );
312 maSlideVisited.push_back( false );
316 bool AnimationSlideController::getSlideAPI( sal_Int32 nSlideNumber, Reference< XDrawPage >& xSlide, Reference< XAnimationNode >& xAnimNode )
318 if( isValidSlideNumber( nSlideNumber ) ) try
320 xSlide.set( mxSlides->getByIndex(nSlideNumber), UNO_QUERY_THROW );
322 if( meMode == PREVIEW )
324 xAnimNode = mxPreviewNode;
326 else
328 Reference< animations::XAnimationNodeSupplier > xAnimNodeSupplier( xSlide, UNO_QUERY_THROW );
329 xAnimNode = xAnimNodeSupplier->getAnimationNode();
332 return true;
334 catch( Exception& )
336 SAL_WARN( "sd", "sd::AnimationSlideController::getSlideAPI(), "
337 "exception caught: "
338 << exceptionToString( cppu::getCaughtException() ) );
341 return false;
344 sal_Int32 AnimationSlideController::findSlideIndex( sal_Int32 nSlideNumber ) const
346 sal_Int32 nIndex;
347 const sal_Int32 nCount = maSlideNumbers.size();
349 for( nIndex = 0; nIndex < nCount; nIndex++ )
351 if( maSlideNumbers[nIndex] == nSlideNumber )
352 return nIndex;
355 return -1;
358 sal_Int32 AnimationSlideController::getNextSlideIndex() const
360 switch( meMode )
362 case ALL:
364 sal_Int32 nNewSlideIndex = mnCurrentSlideIndex + 1;
365 if( isValidIndex( nNewSlideIndex ) )
367 // if the current slide is not excluded, make sure the
368 // next slide is also not excluded.
369 // if the current slide is excluded, we want to go
370 // to the next slide, even if this is also excluded.
371 if( maSlideVisible[mnCurrentSlideIndex] )
373 while( isValidIndex( nNewSlideIndex ) )
375 if( maSlideVisible[nNewSlideIndex] )
376 break;
378 nNewSlideIndex++;
382 return isValidIndex( nNewSlideIndex ) ? nNewSlideIndex : -1;
385 case FROM:
386 case CUSTOM:
387 return mnHiddenSlideNumber == -1 ? mnCurrentSlideIndex + 1 : mnCurrentSlideIndex;
389 default:
390 case PREVIEW:
391 return -1;
396 sal_Int32 AnimationSlideController::getNextSlideNumber() const
398 sal_Int32 nNextSlideIndex = getNextSlideIndex();
399 if( isValidIndex( nNextSlideIndex ) )
401 return maSlideNumbers[nNextSlideIndex];
403 else
405 return -1;
409 bool AnimationSlideController::nextSlide()
411 return jumpToSlideIndex( getNextSlideIndex() );
414 sal_Int32 AnimationSlideController::getPreviousSlideIndex() const
416 sal_Int32 nNewSlideIndex = mnCurrentSlideIndex - 1;
418 switch( meMode )
420 case ALL:
422 // make sure the previous slide is visible
423 // or was already visited
424 while( isValidIndex( nNewSlideIndex ) )
426 if( maSlideVisible[nNewSlideIndex] || maSlideVisited[nNewSlideIndex] )
427 break;
429 nNewSlideIndex--;
432 break;
435 case PREVIEW:
436 return -1;
438 default:
439 break;
442 return nNewSlideIndex;
445 bool AnimationSlideController::previousSlide()
447 return jumpToSlideIndex( getPreviousSlideIndex() );
450 void AnimationSlideController::displayCurrentSlide( const Reference< XSlideShow >& xShow,
451 const Reference< XDrawPagesSupplier>& xDrawPages,
452 const bool bSkipAllMainSequenceEffects )
454 const sal_Int32 nCurrentSlideNumber = getCurrentSlideNumber();
456 if( !(xShow.is() && (nCurrentSlideNumber != -1 )) )
457 return;
459 Reference< XDrawPage > xSlide;
460 Reference< XAnimationNode > xAnimNode;
461 ::std::vector<PropertyValue> aProperties;
463 const sal_Int32 nNextSlideNumber = getNextSlideNumber();
464 if( getSlideAPI( nNextSlideNumber, xSlide, xAnimNode ) )
466 Sequence< Any > aValue(2);
467 aValue[0] <<= xSlide;
468 aValue[1] <<= xAnimNode;
469 aProperties.emplace_back( "Prefetch" ,
471 Any(aValue),
472 PropertyState_DIRECT_VALUE);
474 if (bSkipAllMainSequenceEffects)
476 // Add one property that prevents the slide transition from being
477 // shown (to speed up the transition to the previous slide) and
478 // one to show all main sequence effects so that the user can
479 // continue to undo effects.
480 aProperties.emplace_back( "SkipAllMainSequenceEffects",
482 Any(true),
483 PropertyState_DIRECT_VALUE);
484 aProperties.emplace_back("SkipSlideTransition",
486 Any(true),
487 PropertyState_DIRECT_VALUE);
490 if( getSlideAPI( nCurrentSlideNumber, xSlide, xAnimNode ) )
491 xShow->displaySlide( xSlide, xDrawPages, xAnimNode, comphelper::containerToSequence(aProperties) );
494 static constexpr OUStringLiteral gsOnClick( "OnClick" );
495 static constexpr OUStringLiteral gsBookmark( "Bookmark" );
496 static constexpr OUStringLiteral gsVerb( "Verb" );
498 SlideshowImpl::SlideshowImpl( const Reference< XPresentation2 >& xPresentation, ViewShell* pViewSh, ::sd::View* pView, SdDrawDocument* pDoc, vcl::Window* pParentWindow )
499 : SlideshowImplBase( m_aMutex )
500 , mxModel(pDoc->getUnoModel(),UNO_QUERY_THROW)
501 , mpView(pView)
502 , mpViewShell(pViewSh)
503 , mpDocSh(pDoc->GetDocSh())
504 , mpDoc(pDoc)
505 , mpParentWindow(pParentWindow)
506 , mpShowWindow(nullptr)
507 , mnRestoreSlide(0)
508 , maPresSize( -1, -1 )
509 , meAnimationMode(ANIMATIONMODE_SHOW)
510 , mpOldActiveWindow(nullptr)
511 , mnChildMask( 0 )
512 , mbDisposed(false)
513 , mbAutoSaveWasOn(false)
514 , mbRehearseTimings(false)
515 , mbIsPaused(false)
516 , mbWasPaused(false)
517 , mbInputFreeze(false)
518 , mbActive(false)
519 , maPresSettings( pDoc->getPresentationSettings() )
520 , mnUserPaintColor( 0x80ff0000L )
521 , mbUsePen(false)
522 , mdUserPaintStrokeWidth ( 150.0 )
523 , mnEndShowEvent(nullptr)
524 , mnContextMenuEvent(nullptr)
525 , mxPresentation( xPresentation )
527 if( mpViewShell )
528 mpOldActiveWindow = mpViewShell->GetActiveWindow();
530 maUpdateTimer.SetInvokeHandler(LINK(this, SlideshowImpl, updateHdl));
531 // Priority must not be too high or we'll starve input handling etc.
532 maUpdateTimer.SetPriority(TaskPriority::REPAINT);
534 maDeactivateTimer.SetInvokeHandler(LINK(this, SlideshowImpl, deactivateHdl));
535 maDeactivateTimer.SetTimeout( 20 );
537 maInputFreezeTimer.SetInvokeHandler( LINK( this, SlideshowImpl, ReadyForNextInputHdl ) );
538 maInputFreezeTimer.SetTimeout( 20 );
540 SvtSaveOptions aOptions;
542 // no autosave during show
543 if( aOptions.IsAutoSave() )
544 mbAutoSaveWasOn = true;
546 Application::AddEventListener( LINK( this, SlideshowImpl, EventListenerHdl ) );
548 mbUsePen = maPresSettings.mbMouseAsPen;
550 SdOptions* pOptions = SD_MOD()->GetSdOptions(DocumentType::Impress);
551 if( pOptions )
553 mnUserPaintColor = pOptions->GetPresentationPenColor();
554 mdUserPaintStrokeWidth = pOptions->GetPresentationPenWidth();
558 SlideshowImpl::~SlideshowImpl()
560 SdModule *pModule = SD_MOD();
561 //rhbz#806663 SlideshowImpl can outlive SdModule
562 SdOptions* pOptions = pModule ?
563 pModule->GetSdOptions(DocumentType::Impress) : nullptr;
564 if( pOptions )
566 pOptions->SetPresentationPenColor(mnUserPaintColor);
567 pOptions->SetPresentationPenWidth(mdUserPaintStrokeWidth);
570 Application::RemoveEventListener( LINK( this, SlideshowImpl, EventListenerHdl ) );
572 maDeactivateTimer.Stop();
574 if( !mbDisposed )
576 OSL_FAIL("SlideshowImpl::~SlideshowImpl(), component was not disposed!");
577 disposing();
581 void SAL_CALL SlideshowImpl::disposing()
583 #ifdef ENABLE_SDREMOTE
584 RemoteServer::presentationStopped();
585 #endif
586 if( mxShow.is() && mpDoc )
587 NotifyDocumentEvent(
588 *mpDoc,
589 "OnEndPresentation" );
591 if( mbAutoSaveWasOn )
592 setAutoSaveState( true );
594 if( mnEndShowEvent )
595 Application::RemoveUserEvent( mnEndShowEvent );
596 if( mnContextMenuEvent )
597 Application::RemoveUserEvent( mnContextMenuEvent );
599 maInputFreezeTimer.Stop();
601 SolarMutexGuard aSolarGuard;
603 if( !mxShow.is() )
604 return;
606 if( mxPresentation.is() )
607 mxPresentation->end();
609 maUpdateTimer.Stop();
611 removeShapeEvents();
613 if( mxListenerProxy.is() )
614 mxListenerProxy->removeAsSlideShowListener();
618 if( mxView.is() )
619 mxShow->removeView( mxView.get() );
621 Reference< XComponent > xComponent( mxShow, UNO_QUERY );
622 if( xComponent.is() )
623 xComponent->dispose();
625 if( mxView.is() )
626 mxView->dispose();
628 catch( Exception& )
630 SAL_WARN( "sd", "sd::SlideshowImpl::stop(), exception caught: "
631 << exceptionToString( cppu::getCaughtException() ) );
634 mxShow.clear();
635 mxView.clear();
636 mxListenerProxy.clear();
637 mpSlideController.reset();
639 // take DrawView from presentation window, but give the old window back
640 if( mpShowWindow && mpView )
641 mpView->DeleteWindowFromPaintView( mpShowWindow );
643 if( mpView )
644 mpView->SetAnimationPause( false );
646 if( mpViewShell )
648 mpViewShell->SetActiveWindow(mpOldActiveWindow);
649 if (mpShowWindow)
650 mpShowWindow->SetViewShell( nullptr );
653 if( mpView )
654 mpView->InvalidateAllWin();
656 if( maPresSettings.mbFullScreen )
658 #if HAVE_FEATURE_SCRIPTING
659 // restore StarBASICErrorHdl
660 StarBASIC::SetGlobalErrorHdl(maStarBASICGlobalErrorHdl);
661 maStarBASICGlobalErrorHdl = Link<StarBASIC*,bool>();
662 #endif
664 else
666 if( mpShowWindow )
667 mpShowWindow->Hide();
670 if( meAnimationMode == ANIMATIONMODE_SHOW )
672 mpDocSh->SetSlotFilter();
673 mpDocSh->ApplySlotFilter();
675 Help::EnableContextHelp();
676 Help::EnableExtHelp();
678 showChildWindows();
679 mnChildMask = 0;
682 // show current window again
683 if( mpViewShell && dynamic_cast< PresentationViewShell *>( mpViewShell ) == nullptr)
685 if( meAnimationMode == ANIMATIONMODE_SHOW )
687 mpViewShell->GetViewShellBase().ShowUIControls (true);
688 mpPaneHider.reset();
690 else if( meAnimationMode == ANIMATIONMODE_PREVIEW )
692 mpViewShell->ShowUIControls(true);
696 if( mpShowWindow )
697 mpShowWindow->Hide();
698 mpShowWindow.disposeAndClear();
700 if ( mpViewShell )
702 if( meAnimationMode == ANIMATIONMODE_SHOW )
704 ::sd::Window* pActWin = mpViewShell->GetActiveWindow();
706 if (pActWin)
708 Size aVisSizePixel = pActWin->GetOutputSizePixel();
709 ::tools::Rectangle aVisAreaWin = pActWin->PixelToLogic( ::tools::Rectangle( Point(0,0), aVisSizePixel) );
710 mpViewShell->VisAreaChanged(aVisAreaWin);
711 if (mpView)
712 mpView->VisAreaChanged(pActWin);
713 pActWin->GrabFocus();
717 // restart the custom show dialog if he started us
718 if( mpViewShell->IsStartShowWithDialog() && getDispatcher() )
720 mpViewShell->SetStartShowWithDialog( false );
721 getDispatcher()->Execute( SID_CUSTOMSHOW_DLG, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD );
724 mpViewShell->GetViewShellBase().UpdateBorder(true);
727 if( mpShowWindow )
729 mpShowWindow.disposeAndClear();
732 setActiveXToolbarsVisible( true );
734 mbDisposed = true;
737 bool SlideshowImpl::startPreview(
738 const Reference< XDrawPage >& xDrawPage,
739 const Reference< XAnimationNode >& xAnimationNode,
740 vcl::Window * pParent )
742 bool bRet = false;
746 const Reference<lang::XServiceInfo> xServiceInfo( xDrawPage, UNO_QUERY );
747 if (xServiceInfo.is()) {
748 const Sequence<OUString> supportedServices(
749 xServiceInfo->getSupportedServiceNames() );
750 for ( sal_Int32 pos = supportedServices.getLength(); pos--; ) {
751 if ( supportedServices[pos] == "com.sun.star.drawing.MasterPage" ) {
752 OSL_FAIL("sd::SlideshowImpl::startPreview() "
753 "not allowed on master page!");
754 return false;
759 mxPreviewDrawPage = xDrawPage;
760 mxPreviewAnimationNode = xAnimationNode;
761 meAnimationMode = ANIMATIONMODE_PREVIEW;
763 maPresSettings.mbAll = false;
764 maPresSettings.mbEndless = false;
765 maPresSettings.mbCustomShow = false;
766 maPresSettings.mbManual = false;
767 maPresSettings.mbMouseVisible = false;
768 maPresSettings.mbMouseAsPen = false;
769 maPresSettings.mbLockedPages = false;
770 maPresSettings.mbAlwaysOnTop = false;
771 maPresSettings.mbFullScreen = false;
772 maPresSettings.mbAnimationAllowed = true;
773 maPresSettings.mnPauseTimeout = 0;
774 maPresSettings.mbShowPauseLogo = false;
776 Reference< XDrawPagesSupplier > xDrawPages( mpDoc->getUnoModel(), UNO_QUERY_THROW );
777 Reference< XIndexAccess > xSlides( xDrawPages->getDrawPages(), UNO_QUERY_THROW );
778 mpSlideController.reset( new AnimationSlideController( xSlides, AnimationSlideController::PREVIEW ) );
780 sal_Int32 nSlideNumber = 0;
781 Reference< XPropertySet > xSet( mxPreviewDrawPage, UNO_QUERY_THROW );
782 xSet->getPropertyValue( "Number" ) >>= nSlideNumber;
783 mpSlideController->insertSlideNumber( nSlideNumber-1 );
784 mpSlideController->setPreviewNode( xAnimationNode );
786 mpShowWindow = VclPtr<ShowWindow>::Create( this, ((pParent == nullptr) && mpViewShell) ? mpParentWindow.get() : pParent );
787 if( mpViewShell )
789 mpViewShell->SetActiveWindow( mpShowWindow );
790 mpShowWindow->SetViewShell (mpViewShell);
791 mpViewShell->ShowUIControls (false);
794 if( mpView )
796 mpView->AddWindowToPaintView( mpShowWindow, nullptr );
797 mpView->SetAnimationPause( true );
800 // call resize handler
801 if( pParent )
803 maPresSize = pParent->GetSizePixel();
805 else if( mpViewShell )
807 ::tools::Rectangle aContentRect (mpViewShell->GetViewShellBase().getClientRectangle());
808 if (AllSettings::GetLayoutRTL())
810 aContentRect.SetLeft( aContentRect.Right() );
811 aContentRect.AdjustRight(aContentRect.Right() );
813 maPresSize = aContentRect.GetSize();
814 mpShowWindow->SetPosPixel( aContentRect.TopLeft() );
816 else
818 OSL_FAIL("sd::SlideshowImpl::startPreview(), I need either a parent window or a viewshell!");
820 resize( maPresSize );
822 sal_Int32 nPropertyCount = 1;
823 if( mxPreviewAnimationNode.is() )
824 nPropertyCount++;
826 Sequence< beans::PropertyValue > aProperties(nPropertyCount);
827 aProperties[0].Name = "AutomaticAdvancement";
828 aProperties[0].Value <<= 1.0; // one second timeout
830 if( mxPreviewAnimationNode.is() )
832 aProperties[1].Name = "NoSlideTransitions";
833 aProperties[1].Value <<= true;
836 bRet = startShowImpl( aProperties );
838 if( mpShowWindow != nullptr && meAnimationMode == ANIMATIONMODE_PREVIEW )
839 mpShowWindow->SetPreviewMode();
842 catch( Exception& )
844 SAL_WARN( "sd", "sd::SlideshowImpl::startPreview(), exception caught: "
845 << exceptionToString( cppu::getCaughtException() ) );
846 bRet = false;
849 return bRet;
852 bool SlideshowImpl::startShow( PresentationSettingsEx const * pPresSettings )
854 const rtl::Reference<SlideshowImpl> this_(this);
856 DBG_ASSERT( !mxShow.is(), "sd::SlideshowImpl::startShow(), called twice!" );
857 if( mxShow.is() )
858 return true;
859 DBG_ASSERT( mpParentWindow!=nullptr, "sd::SlideshowImpl::startShow() called without parent window" );
860 if (mpParentWindow == nullptr)
861 return false;
863 // Autoplay (pps/ppsx)
864 if (mpViewShell->GetDoc()->IsStartWithPresentation()){
865 mpViewShell->GetDoc()->SetExitAfterPresenting(true);
868 bool bRet = false;
872 if( pPresSettings )
874 maPresSettings = *pPresSettings;
875 mbRehearseTimings = pPresSettings->mbRehearseTimings;
878 OUString aPresSlide( maPresSettings.maPresPage );
879 SdPage* pStartPage = mpViewShell->GetActualPage();
880 bool bStartWithActualSlide = pStartPage;
882 // times should be measured?
883 if( mbRehearseTimings )
885 maPresSettings.mbEndless = false;
886 maPresSettings.mbManual = true;
887 maPresSettings.mbMouseVisible = true;
888 maPresSettings.mbMouseAsPen = false;
889 maPresSettings.mnPauseTimeout = 0;
890 maPresSettings.mbShowPauseLogo = false;
893 if( pStartPage )
895 if( pStartPage->GetPageKind() == PageKind::Notes )
897 // we are in notes page mode, so get
898 // the corresponding draw page
899 const sal_uInt16 nPgNum = ( pStartPage->GetPageNum() - 2 ) >> 1;
900 pStartPage = mpDoc->GetSdPage( nPgNum, PageKind::Standard );
904 if( bStartWithActualSlide )
906 if ( aPresSlide.isEmpty())
908 // no preset slide yet, so pick current on one
909 aPresSlide = pStartPage->GetName();
910 // if the starting slide is hidden, we can't set slide controller to ALL mode
911 maPresSettings.mbAll = !pStartPage->IsExcluded();
914 if( meAnimationMode != ANIMATIONMODE_SHOW )
916 if( pStartPage->GetPageKind() == PageKind::Standard )
918 maPresSettings.mbAll = false;
923 // build page list
924 createSlideList( maPresSettings.mbAll, aPresSlide );
926 // remember Slide number from where the show was started
927 if( pStartPage )
928 mnRestoreSlide = ( pStartPage->GetPageNum() - 1 ) / 2;
930 if( mpSlideController->hasSlides() )
932 // hide child windows
933 hideChildWindows();
935 mpShowWindow = VclPtr<ShowWindow>::Create( this, mpParentWindow );
936 mpShowWindow->SetMouseAutoHide( !maPresSettings.mbMouseVisible );
937 mpViewShell->SetActiveWindow( mpShowWindow );
938 mpShowWindow->SetViewShell (mpViewShell);
939 mpViewShell->GetViewShellBase().ShowUIControls (false);
940 // Hide the side panes for in-place presentations.
941 if ( ! maPresSettings.mbFullScreen)
942 mpPaneHider.reset(new PaneHider(*mpViewShell,this));
944 // these Slots are forbidden in other views for this document
945 if( mpDocSh )
947 mpDocSh->SetSlotFilter( true, pAllowed );
948 mpDocSh->ApplySlotFilter();
951 Help::DisableContextHelp();
952 Help::DisableExtHelp();
954 if( maPresSettings.mbFullScreen )
956 #if HAVE_FEATURE_SCRIPTING
957 // disable basic ide error handling
958 maStarBASICGlobalErrorHdl = StarBASIC::GetGlobalErrorHdl();
959 StarBASIC::SetGlobalErrorHdl( Link<StarBASIC*,bool>() );
960 #endif
963 // call resize handler
964 maPresSize = mpParentWindow->GetSizePixel();
965 if (!maPresSettings.mbFullScreen)
967 const ::tools::Rectangle& aClientRect = mpViewShell->GetViewShellBase().getClientRectangle();
968 maPresSize = aClientRect.GetSize();
969 mpShowWindow->SetPosPixel( aClientRect.TopLeft() );
970 resize( maPresSize );
973 // #i41824#
974 // Note: In FullScreen Mode the OS (window manager) sends a resize to
975 // the WorkWindow once it actually resized it to full size. The
976 // WorkWindow propagates the resize to the DrawViewShell which calls
977 // resize() at the SlideShow (this). Calling resize here results in a
978 // temporary display of a black window in the window's default size
980 if( mpView )
982 mpView->AddWindowToPaintView( mpShowWindow, nullptr );
983 mpView->SetAnimationPause( true );
986 SfxBindings* pBindings = getBindings();
987 if( pBindings )
989 pBindings->Invalidate( SID_PRESENTATION );
990 pBindings->Invalidate( SID_REHEARSE_TIMINGS );
993 // Defer the sd::ShowWindow's GrabFocus to SlideShow::activate. so that the accessible event can be fired correctly.
994 //mpShowWindow->GrabFocus();
996 std::vector<beans::PropertyValue> aProperties;
997 aProperties.reserve( 4 );
999 aProperties.emplace_back( "AdvanceOnClick" ,
1000 -1, Any( !maPresSettings.mbLockedPages ),
1001 beans::PropertyState_DIRECT_VALUE );
1003 aProperties.emplace_back( "ImageAnimationsAllowed" ,
1004 -1, Any( maPresSettings.mbAnimationAllowed ),
1005 beans::PropertyState_DIRECT_VALUE );
1007 const bool bZOrderEnabled(
1008 SD_MOD()->GetSdOptions( mpDoc->GetDocumentType() )->IsSlideshowRespectZOrder() );
1009 aProperties.emplace_back( "DisableAnimationZOrder" ,
1010 -1, Any( !bZOrderEnabled ),
1011 beans::PropertyState_DIRECT_VALUE );
1013 aProperties.emplace_back( "ForceManualAdvance" ,
1014 -1, Any( maPresSettings.mbManual ),
1015 beans::PropertyState_DIRECT_VALUE );
1017 if( mbUsePen )
1019 aProperties.emplace_back( "UserPaintColor" ,
1020 // User paint color is black by default.
1021 -1, Any( mnUserPaintColor ),
1022 beans::PropertyState_DIRECT_VALUE );
1024 aProperties.emplace_back( "UserPaintStrokeWidth" ,
1025 // User paint color is black by default.
1026 -1, Any( mdUserPaintStrokeWidth ),
1027 beans::PropertyState_DIRECT_VALUE );
1030 if (mbRehearseTimings) {
1031 aProperties.emplace_back( "RehearseTimings" ,
1032 -1, Any(true), beans::PropertyState_DIRECT_VALUE );
1035 bRet = startShowImpl( Sequence<beans::PropertyValue>(
1036 aProperties.data(), aProperties.size() ) );
1040 setActiveXToolbarsVisible( false );
1042 catch (const Exception&)
1044 SAL_WARN( "sd", "sd::SlideshowImpl::startShow(), exception caught: "
1045 << exceptionToString( cppu::getCaughtException() ) );
1046 bRet = false;
1049 return bRet;
1052 bool SlideshowImpl::startShowImpl( const Sequence< beans::PropertyValue >& aProperties )
1056 mxShow.set( createSlideShow(), UNO_SET_THROW );
1058 mxView = new SlideShowView(
1059 *mpShowWindow,
1060 mpDoc,
1061 meAnimationMode,
1062 this,
1063 maPresSettings.mbFullScreen);
1065 // try add wait symbol to properties:
1066 const Reference<rendering::XSpriteCanvas> xSpriteCanvas(
1067 mxView->getCanvas() );
1068 if (xSpriteCanvas.is())
1070 BitmapEx waitSymbolBitmap(BMP_WAIT_ICON);
1071 const Reference<rendering::XBitmap> xBitmap(
1072 vcl::unotools::xBitmapFromBitmapEx( waitSymbolBitmap ) );
1073 if (xBitmap.is())
1075 mxShow->setProperty(
1076 beans::PropertyValue( "WaitSymbolBitmap" ,
1078 makeAny( xBitmap ),
1079 beans::PropertyState_DIRECT_VALUE ) );
1082 BitmapEx pointerSymbolBitmap(BMP_POINTER_ICON);
1083 const Reference<rendering::XBitmap> xPointerBitmap(
1084 vcl::unotools::xBitmapFromBitmapEx( pointerSymbolBitmap ) );
1085 if (xPointerBitmap.is())
1087 mxShow->setProperty(
1088 beans::PropertyValue( "PointerSymbolBitmap" ,
1090 makeAny( xPointerBitmap ),
1091 beans::PropertyState_DIRECT_VALUE ) );
1095 const sal_Int32 nCount = aProperties.getLength();
1096 sal_Int32 nIndex;
1097 for( nIndex = 0; nIndex < nCount; nIndex++ )
1098 mxShow->setProperty( aProperties[nIndex] );
1100 mxShow->addView( mxView.get() );
1102 mxListenerProxy.set( new SlideShowListenerProxy( this, mxShow ) );
1103 mxListenerProxy->addAsSlideShowListener();
1105 NotifyDocumentEvent(
1106 *mpDoc,
1107 "OnStartPresentation");
1108 displaySlideIndex( mpSlideController->getStartSlideIndex() );
1110 return true;
1112 catch( Exception& )
1114 SAL_WARN( "sd", "sd::SlideshowImpl::startShowImpl(), exception caught: "
1115 << exceptionToString( cppu::getCaughtException() ) );
1116 return false;
1120 /** called only by the slideshow view when the first paint event occurs.
1121 This actually starts the slideshow. */
1122 void SlideshowImpl::onFirstPaint()
1124 if( mpShowWindow )
1127 mpShowWindow->SetBackground( Wallpaper( COL_BLACK ) );
1128 mpShowWindow->Erase();
1129 mpShowWindow->SetBackground();
1133 SolarMutexGuard aSolarGuard;
1134 maUpdateTimer.SetTimeout( sal_uLong(100) );
1135 maUpdateTimer.Start();
1138 void SlideshowImpl::paint()
1140 if( mxView.is() ) try
1142 awt::PaintEvent aEvt;
1143 // aEvt.UpdateRect = TODO
1144 mxView->paint( aEvt );
1146 catch( Exception& )
1148 SAL_WARN( "sd", "sd::SlideshowImpl::paint(), exception caught: "
1149 << exceptionToString( cppu::getCaughtException() ) );
1153 void SAL_CALL SlideshowImpl::addSlideShowListener( const Reference< XSlideShowListener >& xListener )
1155 if( mxListenerProxy.is() )
1156 mxListenerProxy->addSlideShowListener( xListener );
1159 void SAL_CALL SlideshowImpl::removeSlideShowListener( const Reference< XSlideShowListener >& xListener )
1161 if( mxListenerProxy.is() )
1162 mxListenerProxy->removeSlideShowListener( xListener );
1165 void SlideshowImpl::slideEnded(const bool bReverse)
1167 if (bReverse)
1168 gotoPreviousSlide(true);
1169 else
1170 gotoNextSlide();
1173 bool SlideshowImpl::swipe(const CommandSwipeData &rSwipeData)
1175 if (mbUsePen || mnContextMenuEvent)
1176 return false;
1177 double nVelocityX = rSwipeData.getVelocityX();
1178 // tdf#108475 make it swipe only if some reasonable movement was involved
1179 if (fabs(nVelocityX) < 50)
1180 return false;
1181 if (nVelocityX > 0)
1183 gotoPreviousSlide();
1185 else
1187 gotoNextEffect();
1189 //a swipe is followed by a mouse up, tell the view to ignore that mouse up as we've reacted
1190 //to the swipe instead
1191 mxView->ignoreNextMouseReleased();
1192 return true;
1195 bool SlideshowImpl::longpress(const CommandLongPressData &rLongPressData)
1197 if (mnContextMenuEvent)
1198 return false;
1200 maPopupMousePos = Point(rLongPressData.getX(), rLongPressData.getY());
1201 mnContextMenuEvent = Application::PostUserEvent( LINK( this, SlideshowImpl, ContextMenuHdl ) );
1203 return true;
1206 void SlideshowImpl::removeShapeEvents()
1208 if( !(mxShow.is() && mxListenerProxy.is()) )
1209 return;
1213 for( const auto& rEntry : maShapeEventMap )
1215 mxListenerProxy->removeShapeEventListener( rEntry.first );
1216 mxShow->setShapeCursor( rEntry.first, awt::SystemPointer::ARROW );
1219 maShapeEventMap.clear();
1221 catch( Exception& )
1223 SAL_WARN( "sd", "sd::SlideshowImpl::removeShapeEvents(), exception caught: "
1224 << exceptionToString( cppu::getCaughtException() ) );
1228 void SlideshowImpl::registerShapeEvents(sal_Int32 nSlideNumber)
1230 if( nSlideNumber < 0 )
1231 return;
1235 Reference< XDrawPagesSupplier > xDrawPages( mxModel, UNO_QUERY_THROW );
1236 Reference< XIndexAccess > xPages( xDrawPages->getDrawPages(), UNO_QUERY_THROW );
1238 Reference< XShapes > xDrawPage;
1239 xPages->getByIndex(nSlideNumber) >>= xDrawPage;
1241 if( xDrawPage.is() )
1243 Reference< XMasterPageTarget > xMasterPageTarget( xDrawPage, UNO_QUERY );
1244 if( xMasterPageTarget.is() )
1246 Reference< XShapes > xMasterPage( xMasterPageTarget->getMasterPage(), UNO_QUERY );
1247 if( xMasterPage.is() )
1248 registerShapeEvents( xMasterPage );
1250 registerShapeEvents( xDrawPage );
1253 catch( Exception& )
1255 SAL_WARN( "sd", "sd::SlideshowImpl::registerShapeEvents(), exception caught: "
1256 << exceptionToString( cppu::getCaughtException() ) );
1260 void SlideshowImpl::registerShapeEvents( Reference< XShapes > const & xShapes )
1264 const sal_Int32 nShapeCount = xShapes->getCount();
1265 sal_Int32 nShape;
1266 for( nShape = 0; nShape < nShapeCount; nShape++ )
1268 Reference< XShape > xShape;
1269 xShapes->getByIndex( nShape ) >>= xShape;
1271 if( xShape.is() && xShape->getShapeType() == "com.sun.star.drawing.GroupShape" )
1273 Reference< XShapes > xSubShapes( xShape, UNO_QUERY );
1274 if( xSubShapes.is() )
1275 registerShapeEvents( xSubShapes );
1278 Reference< XPropertySet > xSet( xShape, UNO_QUERY );
1279 if( !xSet.is() )
1280 continue;
1282 Reference< XPropertySetInfo > xSetInfo( xSet->getPropertySetInfo() );
1283 if( !xSetInfo.is() || !xSetInfo->hasPropertyByName( gsOnClick ) )
1284 continue;
1286 WrappedShapeEventImplPtr pEvent( new WrappedShapeEventImpl );
1287 xSet->getPropertyValue( gsOnClick ) >>= pEvent->meClickAction;
1289 switch( pEvent->meClickAction )
1291 case ClickAction_PREVPAGE:
1292 case ClickAction_NEXTPAGE:
1293 case ClickAction_FIRSTPAGE:
1294 case ClickAction_LASTPAGE:
1295 case ClickAction_STOPPRESENTATION:
1296 break;
1297 case ClickAction_BOOKMARK:
1298 if( xSetInfo->hasPropertyByName( gsBookmark ) )
1299 xSet->getPropertyValue( gsBookmark ) >>= pEvent->maStrBookmark;
1300 if( getSlideNumberForBookmark( pEvent->maStrBookmark ) == -1 )
1301 continue;
1302 break;
1303 case ClickAction_DOCUMENT:
1304 case ClickAction_SOUND:
1305 case ClickAction_PROGRAM:
1306 case ClickAction_MACRO:
1307 if( xSetInfo->hasPropertyByName( gsBookmark ) )
1308 xSet->getPropertyValue( gsBookmark ) >>= pEvent->maStrBookmark;
1309 break;
1310 case ClickAction_VERB:
1311 if( xSetInfo->hasPropertyByName( gsVerb ) )
1312 xSet->getPropertyValue( gsVerb ) >>= pEvent->mnVerb;
1313 break;
1314 default:
1315 continue; // skip all others
1318 maShapeEventMap[ xShape ] = pEvent;
1320 if( mxListenerProxy.is() )
1321 mxListenerProxy->addShapeEventListener( xShape );
1322 mxShow->setShapeCursor( xShape, awt::SystemPointer::REFHAND );
1325 catch( Exception& )
1327 SAL_WARN( "sd", "sd::SlideshowImpl::registerShapeEvents(), exception caught: "
1328 << exceptionToString( cppu::getCaughtException() ) );
1332 void SlideshowImpl::displayCurrentSlide (const bool bSkipAllMainSequenceEffects)
1334 stopSound();
1335 removeShapeEvents();
1337 if( mpSlideController.get() && mxShow.is() )
1339 Reference< XDrawPagesSupplier > xDrawPages( mpDoc->getUnoModel(),
1340 UNO_QUERY_THROW );
1341 mpSlideController->displayCurrentSlide( mxShow, xDrawPages, bSkipAllMainSequenceEffects );
1342 registerShapeEvents(mpSlideController->getCurrentSlideNumber());
1343 update();
1346 // send out page change event and notify to update all acc info for current page
1347 if (mpViewShell)
1349 sal_Int32 currentPageIndex = getCurrentSlideIndex();
1350 mpViewShell->fireSwitchCurrentPage(currentPageIndex);
1351 mpViewShell->NotifyAccUpdate();
1355 void SlideshowImpl::endPresentation()
1357 if( maPresSettings.mbMouseAsPen)
1359 Reference< XMultiServiceFactory > xDocFactory(mpDoc->getUnoModel(), UNO_QUERY );
1360 if( xDocFactory.is() )
1361 mxShow->registerUserPaintPolygons(xDocFactory);
1364 if( !mnEndShowEvent )
1365 mnEndShowEvent = Application::PostUserEvent( LINK(this, SlideshowImpl, endPresentationHdl) );
1368 IMPL_LINK_NOARG(SlideshowImpl, endPresentationHdl, void*, void)
1370 mnEndShowEvent = nullptr;
1372 if( mxPresentation.is() )
1373 mxPresentation->end();
1376 void SAL_CALL SlideshowImpl::pause()
1378 SolarMutexGuard aSolarGuard;
1380 if( mbIsPaused )
1381 return;
1385 mbIsPaused = true;
1386 if( mxShow.is() )
1388 mxShow->pause(true);
1390 if( mxListenerProxy.is() )
1391 mxListenerProxy->paused();
1394 catch( Exception& )
1396 SAL_WARN( "sd", "sd::SlideshowImpl::pause(), exception caught: "
1397 << exceptionToString( cppu::getCaughtException() ) );
1401 void SAL_CALL SlideshowImpl::resume()
1403 SolarMutexGuard aSolarGuard;
1405 if( mbIsPaused ) try
1407 if( mpShowWindow->GetShowWindowMode() == SHOWWINDOWMODE_BLANK )
1409 mpShowWindow->RestartShow();
1411 else
1413 mbIsPaused = false;
1414 if( mxShow.is() )
1416 mxShow->pause(false);
1417 update();
1419 if( mxListenerProxy.is() )
1420 mxListenerProxy->resumed();
1424 catch( Exception& )
1426 SAL_WARN( "sd", "sd::SlideshowImpl::resume(), exception caught: "
1427 << exceptionToString( cppu::getCaughtException() ) );
1429 #ifdef ENABLE_SDREMOTE
1430 RemoteServer::presentationStarted( this );
1431 #endif
1434 sal_Bool SAL_CALL SlideshowImpl::isPaused()
1436 SolarMutexGuard aSolarGuard;
1437 return mbIsPaused;
1440 void SAL_CALL SlideshowImpl::blankScreen( sal_Int32 nColor )
1442 SolarMutexGuard aSolarGuard;
1444 if( mpShowWindow && mpSlideController )
1446 if( mpShowWindow->SetBlankMode( mpSlideController->getCurrentSlideIndex(), Color(nColor) ) )
1448 pause();
1453 // XShapeEventListener
1455 void SlideshowImpl::click( const Reference< XShape >& xShape )
1457 SolarMutexGuard aSolarGuard;
1459 WrappedShapeEventImplPtr pEvent = maShapeEventMap[xShape];
1460 if( !pEvent.get() )
1461 return;
1463 switch( pEvent->meClickAction )
1465 case ClickAction_PREVPAGE: gotoPreviousSlide(); break;
1466 case ClickAction_NEXTPAGE: gotoNextSlide(); break;
1467 case ClickAction_FIRSTPAGE: gotoFirstSlide(); break;
1468 case ClickAction_LASTPAGE: gotoLastSlide(); break;
1469 case ClickAction_STOPPRESENTATION: endPresentation(); break;
1470 case ClickAction_BOOKMARK:
1472 gotoBookmark( pEvent->maStrBookmark );
1474 break;
1475 case ClickAction_SOUND:
1477 #if HAVE_FEATURE_AVMEDIA
1480 mxPlayer.set(avmedia::MediaWindow::createPlayer(pEvent->maStrBookmark, ""/*TODO?*/), uno::UNO_SET_THROW );
1481 mxPlayer->start();
1483 catch( uno::Exception& )
1485 OSL_FAIL("sd::SlideshowImpl::click(), exception caught!" );
1487 #endif
1489 break;
1491 case ClickAction_DOCUMENT:
1493 OUString aBookmark( pEvent->maStrBookmark );
1495 sal_Int32 nPos = aBookmark.indexOf( '#' );
1496 if( nPos >= 0 )
1498 OUString aURL( aBookmark.copy( 0, nPos+1 ) );
1499 OUString aName( aBookmark.copy( nPos+1 ) );
1500 aURL += getUiNameFromPageApiNameImpl( aName );
1501 aBookmark = aURL;
1504 mpDocSh->OpenBookmark( aBookmark );
1506 break;
1508 case ClickAction_PROGRAM:
1510 INetURLObject aURL(
1511 ::URIHelper::SmartRel2Abs(
1512 INetURLObject(mpDocSh->GetMedium()->GetBaseURL()),
1513 pEvent->maStrBookmark, ::URIHelper::GetMaybeFileHdl(), true,
1514 false, INetURLObject::EncodeMechanism::WasEncoded,
1515 INetURLObject::DecodeMechanism::Unambiguous ) );
1517 if( INetProtocol::File == aURL.GetProtocol() )
1519 SfxStringItem aUrl( SID_FILE_NAME, aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
1520 SfxBoolItem aBrowsing( SID_BROWSE, true );
1522 SfxViewFrame* pViewFrm = SfxViewFrame::Current();
1523 if (pViewFrm)
1525 pViewFrm->GetDispatcher()->ExecuteList( SID_OPENDOC,
1526 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD,
1527 { &aUrl, &aBrowsing });
1531 break;
1533 case presentation::ClickAction_MACRO:
1535 const OUString aMacro( pEvent->maStrBookmark );
1537 if ( SfxApplication::IsXScriptURL( aMacro ) )
1539 Any aRet;
1540 Sequence< sal_Int16 > aOutArgsIndex;
1541 Sequence< Any > aOutArgs;
1542 Sequence< Any >* pInArgs = new Sequence< Any >(0);
1543 mpDocSh->CallXScript( aMacro, *pInArgs, aRet, aOutArgsIndex, aOutArgs);
1545 else
1547 // aMacro has the following syntax:
1548 // "Macroname.Modulname.Libname.Documentname" or
1549 // "Macroname.Modulname.Libname.Applicationname"
1550 sal_Int32 nIdx{ 0 };
1551 const OUString aMacroName = aMacro.getToken(0, '.', nIdx);
1552 const OUString aModulName = aMacro.getToken(0, '.', nIdx);
1554 // todo: is the limitation still given that only
1555 // Modulname+Macroname can be used here?
1556 OUString aExecMacro = aModulName + "." + aMacroName;
1557 mpDocSh->GetBasic()->Call(aExecMacro);
1560 break;
1562 case ClickAction_VERB:
1564 // todo, better do it async?
1565 SdrObject* pObj = GetSdrObjectFromXShape( xShape );
1566 SdrOle2Obj* pOleObject = dynamic_cast< SdrOle2Obj* >(pObj);
1567 if (pOleObject && mpViewShell )
1568 mpViewShell->ActivateObject(pOleObject, pEvent->mnVerb);
1570 break;
1571 default:
1572 break;
1576 sal_Int32 SlideshowImpl::getSlideNumberForBookmark( const OUString& rStrBookmark )
1578 bool bIsMasterPage;
1579 OUString aBookmark = getUiNameFromPageApiNameImpl( rStrBookmark );
1580 sal_uInt16 nPgNum = mpDoc->GetPageByName( aBookmark, bIsMasterPage );
1582 if( nPgNum == SDRPAGE_NOTFOUND )
1584 // Is the bookmark an object?
1585 SdrObject* pObj = mpDoc->GetObj( aBookmark );
1587 if( pObj )
1589 nPgNum = pObj->getSdrPageFromSdrObject()->GetPageNum();
1590 bIsMasterPage = pObj->getSdrPageFromSdrObject()->IsMasterPage();
1594 if( (nPgNum == SDRPAGE_NOTFOUND) || bIsMasterPage || static_cast<SdPage*>(mpDoc->GetPage(nPgNum))->GetPageKind() != PageKind::Standard )
1595 return -1;
1597 return ( nPgNum - 1) >> 1;
1600 void SlideshowImpl::hyperLinkClicked( OUString const& aHyperLink )
1602 OUString aBookmark( aHyperLink );
1604 sal_Int32 nPos = aBookmark.indexOf( '#' );
1605 if( nPos >= 0 )
1607 OUString aURL( aBookmark.copy( 0, nPos+1 ) );
1608 OUString aName( aBookmark.copy( nPos+1 ) );
1609 aURL += getUiNameFromPageApiNameImpl( aName );
1610 aBookmark = aURL;
1613 mpDocSh->OpenBookmark( aBookmark );
1616 void SlideshowImpl::displaySlideNumber( sal_Int32 nSlideNumber )
1618 if( mpSlideController.get() )
1620 if( mpSlideController->jumpToSlideNumber( nSlideNumber ) )
1622 displayCurrentSlide();
1627 /** nSlideIndex == -1 displays current slide again */
1628 void SlideshowImpl::displaySlideIndex( sal_Int32 nSlideIndex )
1630 if( mpSlideController.get() )
1632 if( (nSlideIndex == -1) || mpSlideController->jumpToSlideIndex( nSlideIndex ) )
1634 displayCurrentSlide();
1639 void SlideshowImpl::jumpToBookmark( const OUString& sBookmark )
1641 sal_Int32 nSlideNumber = getSlideNumberForBookmark( sBookmark );
1642 if( nSlideNumber != -1 )
1643 displaySlideNumber( nSlideNumber );
1646 sal_Int32 SlideshowImpl::getCurrentSlideNumber()
1648 return mpSlideController.get() ? mpSlideController->getCurrentSlideNumber() : -1;
1651 sal_Bool SAL_CALL SlideshowImpl::isEndless()
1653 SolarMutexGuard aSolarGuard;
1654 return maPresSettings.mbEndless;
1657 void SlideshowImpl::update()
1659 startUpdateTimer();
1662 void SlideshowImpl::startUpdateTimer()
1664 SolarMutexGuard aSolarGuard;
1665 maUpdateTimer.SetTimeout( 0 );
1666 maUpdateTimer.Start();
1669 /** this timer is called 20ms after a new slide was displayed.
1670 This is used to unfreeze user input that was disabled after
1671 slide change to skip input that was buffered during slide
1672 transition preparation */
1673 IMPL_LINK_NOARG(SlideshowImpl, ReadyForNextInputHdl, Timer *, void)
1675 mbInputFreeze = false;
1678 /** if I catch someone someday who calls this method by hand
1679 and not by using the timer, I will personally punish this
1680 person seriously, even if this person is me.
1682 IMPL_LINK_NOARG(SlideshowImpl, updateHdl, Timer *, void)
1684 updateSlideShow();
1687 void SlideshowImpl::updateSlideShow()
1689 // prevent me from deletion when recursing (App::EnableYieldMode does)
1690 const rtl::Reference<SlideshowImpl> this_(this);
1692 Reference< XSlideShow > xShow( mxShow );
1693 if ( ! xShow.is())
1694 return;
1698 double fUpdate = 0.0;
1699 if( !xShow->update(fUpdate) )
1700 fUpdate = -1.0;
1702 if (mxShow.is() && (fUpdate >= 0.0))
1704 if (::basegfx::fTools::equalZero(fUpdate))
1706 // Make sure idle tasks don't starve when we don't have to wait.
1707 Scheduler::ProcessEventsToIdle();
1709 else
1711 // Avoid busy loop when the previous call to update()
1712 // returns a small positive number but not 0 (which is
1713 // handled above). Also, make sure that calls to update()
1714 // have a minimum frequency.
1715 // => Allow up to 60 frames per second. Call at least once
1716 // every 4 seconds.
1717 const static sal_Int32 nMaximumFrameCount (60);
1718 const static double nMinimumTimeout (1.0 / nMaximumFrameCount);
1719 const static double nMaximumTimeout (4.0);
1720 fUpdate = std::clamp(fUpdate, nMinimumTimeout, nMaximumTimeout);
1722 // Make sure that the maximum frame count has not been set
1723 // too high (only then conversion to milliseconds and long
1724 // integer may lead to zero value.)
1725 OSL_ASSERT(static_cast<sal_uLong>(fUpdate * 1000.0) > 0);
1728 // Use our high resolution timers for the asynchronous callback.
1729 maUpdateTimer.SetTimeout(static_cast<sal_uLong>(fUpdate * 1000.0));
1730 maUpdateTimer.Start();
1733 catch( Exception& )
1735 SAL_WARN( "sd", "sd::SlideshowImpl::updateSlideShow(), exception caught: "
1736 << exceptionToString( cppu::getCaughtException() ) );
1740 bool SlideshowImpl::keyInput(const KeyEvent& rKEvt)
1742 if( !mxShow.is() || mbInputFreeze )
1743 return false;
1745 bool bRet = true;
1749 const int nKeyCode = rKEvt.GetKeyCode().GetCode();
1750 switch( nKeyCode )
1752 case awt::Key::CONTEXTMENU:
1753 if( !mnContextMenuEvent )
1755 if( mpShowWindow )
1756 maPopupMousePos = mpShowWindow->GetPointerState().maPos;
1757 mnContextMenuEvent = Application::PostUserEvent( LINK( this, SlideshowImpl, ContextMenuHdl ) );
1759 break;
1761 // cancel show
1762 case KEY_ESCAPE:
1763 case KEY_SUBTRACT:
1764 // in case the user cancels the presentation, switch to current slide
1765 // in edit mode
1766 if( mpSlideController.get() && (ANIMATIONMODE_SHOW == meAnimationMode) )
1768 if( mpSlideController->getCurrentSlideNumber() != -1 )
1769 mnRestoreSlide = mpSlideController->getCurrentSlideNumber();
1771 endPresentation();
1772 break;
1774 // advance show
1775 case KEY_PAGEDOWN:
1776 if(rKEvt.GetKeyCode().IsMod2())
1778 gotoNextSlide();
1779 break;
1781 [[fallthrough]];
1782 case KEY_SPACE:
1783 case KEY_RIGHT:
1784 case KEY_DOWN:
1785 case KEY_N:
1786 gotoNextEffect();
1787 break;
1789 case KEY_RETURN:
1791 if( !maCharBuffer.isEmpty() )
1793 if( mpSlideController.get() )
1795 if( mpSlideController->jumpToSlideNumber( maCharBuffer.toInt32() - 1 ) )
1796 displayCurrentSlide();
1798 maCharBuffer.clear();
1800 else
1802 gotoNextEffect();
1805 break;
1807 // numeric: add to buffer
1808 case KEY_0:
1809 case KEY_1:
1810 case KEY_2:
1811 case KEY_3:
1812 case KEY_4:
1813 case KEY_5:
1814 case KEY_6:
1815 case KEY_7:
1816 case KEY_8:
1817 case KEY_9:
1818 maCharBuffer += OUStringLiteral1( rKEvt.GetCharCode() );
1819 break;
1821 case KEY_PAGEUP:
1822 if(rKEvt.GetKeyCode().IsMod2())
1824 gotoPreviousSlide();
1825 break;
1827 [[fallthrough]];
1828 case KEY_LEFT:
1829 case KEY_UP:
1830 case KEY_P:
1831 case KEY_BACKSPACE:
1832 gotoPreviousEffect();
1833 break;
1835 case KEY_HOME:
1836 gotoFirstSlide();
1837 break;
1839 case KEY_END:
1840 gotoLastSlide();
1841 break;
1843 case KEY_B:
1844 case KEY_W:
1845 case KEY_POINT:
1846 case KEY_COMMA:
1848 blankScreen( ((nKeyCode == KEY_W ) || (nKeyCode == KEY_COMMA)) ? 0x00ffffff : 0x00000000 );
1850 break;
1852 default:
1853 bRet = false;
1854 break;
1857 catch( Exception& )
1859 bRet = false;
1860 SAL_WARN( "sd", "sd::SlideshowImpl::keyInput(), exception caught: "
1861 << exceptionToString( cppu::getCaughtException() ) );
1864 return bRet;
1867 IMPL_LINK( SlideshowImpl, EventListenerHdl, VclSimpleEvent&, rSimpleEvent, void )
1869 if( !mxShow.is() || mbInputFreeze )
1870 return;
1872 if( !((rSimpleEvent.GetId() == VclEventId::WindowCommand) && static_cast<VclWindowEvent*>(&rSimpleEvent)->GetData()) )
1873 return;
1875 const CommandEvent& rEvent = *static_cast<const CommandEvent*>(static_cast<VclWindowEvent*>(&rSimpleEvent)->GetData());
1877 if( rEvent.GetCommand() != CommandEventId::Media )
1878 return;
1880 CommandMediaData* pMediaData = rEvent.GetMediaData();
1881 pMediaData->SetPassThroughToOS(false);
1882 switch (pMediaData->GetMediaId())
1884 #if defined( MACOSX )
1885 case MediaCommand::Menu:
1886 if( !mnContextMenuEvent )
1888 if( mpShowWindow )
1889 maPopupMousePos = mpShowWindow->GetPointerState().maPos;
1890 mnContextMenuEvent = Application::PostUserEvent( LINK( this, SlideshowImpl, ContextMenuHdl ) );
1892 break;
1893 case MediaCommand::VolumeDown:
1894 gotoPreviousSlide();
1895 break;
1896 case MediaCommand::VolumeUp:
1897 gotoNextEffect();
1898 break;
1899 #endif
1900 case MediaCommand::NextTrack:
1901 gotoNextEffect();
1902 break;
1903 case MediaCommand::Pause:
1904 if( !mbIsPaused )
1905 blankScreen(0);
1906 break;
1907 case MediaCommand::Play:
1908 if( mbIsPaused )
1909 resume();
1910 break;
1912 case MediaCommand::PlayPause:
1913 if( mbIsPaused )
1914 resume();
1915 else
1916 blankScreen(0);
1917 break;
1918 case MediaCommand::PreviousTrack:
1919 gotoPreviousSlide();
1920 break;
1921 case MediaCommand::NextTrackHold:
1922 gotoLastSlide();
1923 break;
1925 case MediaCommand::Rewind:
1926 gotoFirstSlide();
1927 break;
1928 case MediaCommand::Stop:
1929 // in case the user cancels the presentation, switch to current slide
1930 // in edit mode
1931 if( mpSlideController.get() && (ANIMATIONMODE_SHOW == meAnimationMode) )
1933 if( mpSlideController->getCurrentSlideNumber() != -1 )
1934 mnRestoreSlide = mpSlideController->getCurrentSlideNumber();
1936 endPresentation();
1937 break;
1938 default:
1939 pMediaData->SetPassThroughToOS(true);
1940 break;
1944 void SlideshowImpl::mouseButtonUp(const MouseEvent& rMEvt)
1946 if( rMEvt.IsRight() && !mnContextMenuEvent )
1948 maPopupMousePos = rMEvt.GetPosPixel();
1949 mnContextMenuEvent = Application::PostUserEvent( LINK( this, SlideshowImpl, ContextMenuHdl ) );
1953 IMPL_LINK_NOARG(SlideshowImpl, ContextMenuHdl, void*, void)
1955 mnContextMenuEvent = nullptr;
1957 if (mpSlideController == nullptr)
1958 return;
1960 mbWasPaused = mbIsPaused;
1961 if( !mbWasPaused )
1962 pause();
1964 VclBuilder aBuilder(nullptr, VclBuilderContainer::getUIRootDir(), "modules/simpress/ui/slidecontextmenu.ui", "");
1965 VclPtr<PopupMenu> pMenu(aBuilder.get_menu("menu"));
1967 // Adding button to display if in Pen mode
1968 pMenu->CheckItem("pen", mbUsePen);
1970 const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode();
1971 pMenu->EnableItem(pMenu->GetItemId("next"), mpSlideController->getNextSlideIndex() != -1);
1972 pMenu->EnableItem(pMenu->GetItemId("prev"), (mpSlideController->getPreviousSlideIndex() != -1 ) || (eMode == SHOWWINDOWMODE_END) || (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK));
1973 pMenu->EnableItem(pMenu->GetItemId("edit"), mpViewShell->GetDoc()->IsStartWithPresentation());
1975 PopupMenu* pPageMenu = pMenu->GetPopupMenu(pMenu->GetItemId("goto"));
1977 SfxViewFrame* pViewFrame = getViewFrame();
1978 if( pViewFrame )
1980 Reference< css::frame::XFrame > xFrame( pViewFrame->GetFrame().GetFrameInterface() );
1981 if( xFrame.is() )
1983 pMenu->SetItemImage(pMenu->GetItemId("next"), vcl::CommandInfoProvider::GetImageForCommand(".uno:NextRecord", xFrame));
1984 pMenu->SetItemImage(pMenu->GetItemId("prev"), vcl::CommandInfoProvider::GetImageForCommand(".uno:PrevRecord", xFrame));
1986 if( pPageMenu )
1988 pPageMenu->SetItemImage(pPageMenu->GetItemId("first"), vcl::CommandInfoProvider::GetImageForCommand(".uno:FirstRecord", xFrame));
1989 pPageMenu->SetItemImage(pPageMenu->GetItemId("last"), vcl::CommandInfoProvider::GetImageForCommand(".uno:LastRecord", xFrame));
1994 // populate slide goto list
1995 if( pPageMenu )
1997 const sal_Int32 nPageNumberCount = mpSlideController->getSlideNumberCount();
1998 if( nPageNumberCount <= 1 )
2000 pMenu->EnableItem(pMenu->GetItemId("goto"), false);
2002 else
2004 sal_Int32 nCurrentSlideNumber = mpSlideController->getCurrentSlideNumber();
2005 if( (eMode == SHOWWINDOWMODE_END) || (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) )
2006 nCurrentSlideNumber = -1;
2008 pPageMenu->EnableItem(pPageMenu->GetItemId("first"), mpSlideController->getSlideNumber(0) != nCurrentSlideNumber);
2009 pPageMenu->EnableItem(pPageMenu->GetItemId("last"), mpSlideController->getSlideNumber(mpSlideController->getSlideIndexCount() - 1) != nCurrentSlideNumber);
2011 sal_Int32 nPageNumber;
2013 for( nPageNumber = 0; nPageNumber < nPageNumberCount; nPageNumber++ )
2015 if( mpSlideController->isVisibleSlideNumber( nPageNumber ) )
2017 SdPage* pPage = mpDoc->GetSdPage(static_cast<sal_uInt16>(nPageNumber), PageKind::Standard);
2018 if (pPage)
2020 pPageMenu->InsertItem( static_cast<sal_uInt16>(CM_SLIDES + nPageNumber), pPage->GetName() );
2021 if( nPageNumber == nCurrentSlideNumber )
2022 pPageMenu->CheckItem( static_cast<sal_uInt16>(CM_SLIDES + nPageNumber) );
2029 if( mpShowWindow->GetShowWindowMode() == SHOWWINDOWMODE_BLANK )
2031 PopupMenu* pBlankMenu = pMenu->GetPopupMenu(pMenu->GetItemId("screen"));
2032 if( pBlankMenu )
2034 pBlankMenu->CheckItem((mpShowWindow->GetBlankColor() == COL_WHITE) ? "white" : "black");
2038 PopupMenu* pWidthMenu = pMenu->GetPopupMenu(pMenu->GetItemId("width"));
2040 // populate color width list
2041 if( pWidthMenu )
2043 sal_Int32 nIterator;
2044 double nWidth;
2046 nWidth = 4.0;
2047 for( nIterator = 1; nIterator < 6; nIterator++)
2049 switch(nIterator)
2051 case 1:
2052 nWidth = 4.0;
2053 break;
2054 case 2:
2055 nWidth = 100.0;
2056 break;
2057 case 3:
2058 nWidth = 150.0;
2059 break;
2060 case 4:
2061 nWidth = 200.0;
2062 break;
2063 case 5:
2064 nWidth = 400.0;
2065 break;
2066 default:
2067 break;
2070 if (nWidth == mdUserPaintStrokeWidth)
2071 pWidthMenu->CheckItem(OString::number(nWidth));
2075 pMenu->SetSelectHdl( LINK( this, SlideshowImpl, ContextMenuSelectHdl ) );
2076 pMenu->Execute( mpShowWindow, maPopupMousePos );
2078 if( mxView.is() )
2079 mxView->ignoreNextMouseReleased();
2081 if( !mbWasPaused )
2082 resume();
2085 IMPL_LINK( SlideshowImpl, ContextMenuSelectHdl, Menu *, pMenu, bool )
2087 if (!pMenu)
2088 return false;
2090 OString sMenuId = pMenu->GetCurItemIdent();
2092 if (sMenuId == "prev")
2094 gotoPreviousSlide();
2095 mbWasPaused = false;
2097 else if(sMenuId == "next")
2099 gotoNextSlide();
2100 mbWasPaused = false;
2102 else if (sMenuId == "first")
2104 gotoFirstSlide();
2105 mbWasPaused = false;
2107 else if (sMenuId == "last")
2109 gotoLastSlide();
2110 mbWasPaused = false;
2112 else if (sMenuId == "black" || sMenuId == "white")
2114 const Color aBlankColor(sMenuId == "white" ? COL_WHITE : COL_BLACK);
2115 if( mbWasPaused )
2117 if( mpShowWindow->GetShowWindowMode() == SHOWWINDOWMODE_BLANK )
2119 if( mpShowWindow->GetBlankColor() == aBlankColor )
2121 mbWasPaused = false;
2122 mpShowWindow->RestartShow();
2123 return false;
2126 mpShowWindow->RestartShow();
2128 if( mpShowWindow->SetBlankMode( mpSlideController->getCurrentSlideIndex(), aBlankColor ) )
2130 pause();
2131 mbWasPaused = true;
2134 else if (sMenuId == "color")
2136 //Open a color picker based on SvColorDialog
2137 ::Color aColor( mnUserPaintColor );
2138 SvColorDialog aColorDlg;
2139 aColorDlg.SetColor( aColor );
2141 if (aColorDlg.Execute(mpShowWindow->GetFrameWeld()))
2143 aColor = aColorDlg.GetColor();
2144 setPenColor(sal_Int32(aColor));
2146 mbWasPaused = false;
2148 else if (sMenuId == "4")
2150 setPenWidth(4.0);
2151 mbWasPaused = false;
2153 else if (sMenuId == "100")
2155 setPenWidth(100.0);
2156 mbWasPaused = false;
2158 else if (sMenuId == "150")
2160 setPenWidth(150.0);
2161 mbWasPaused = false;
2163 else if (sMenuId == "200")
2165 setPenWidth(200.0);
2166 mbWasPaused = false;
2168 else if (sMenuId == "400")
2170 setPenWidth(400.0);
2171 mbWasPaused = false;
2173 else if (sMenuId == "erase")
2175 setEraseAllInk(true);
2176 mbWasPaused = false;
2178 else if (sMenuId == "pen")
2180 setUsePen(!mbUsePen);
2181 mbWasPaused = false;
2183 else if (sMenuId == "edit")
2185 // When in autoplay mode (pps/ppsx), offer editing of the presentation
2186 // Turn autostart off, else Impress will close when exiting the Presentation
2187 mpViewShell->GetDoc()->SetExitAfterPresenting(false);
2188 if( mpSlideController.get() && (ANIMATIONMODE_SHOW == meAnimationMode) )
2190 if( mpSlideController->getCurrentSlideNumber() != -1 )
2192 mnRestoreSlide = mpSlideController->getCurrentSlideNumber();
2195 endPresentation();
2197 else if (sMenuId == "end")
2199 // in case the user cancels the presentation, switch to current slide
2200 // in edit mode
2201 if( mpSlideController.get() && (ANIMATIONMODE_SHOW == meAnimationMode) )
2203 if( mpSlideController->getCurrentSlideNumber() != -1 )
2205 mnRestoreSlide = mpSlideController->getCurrentSlideNumber();
2208 endPresentation();
2210 else
2212 sal_Int32 nPageNumber = pMenu->GetCurItemId() - CM_SLIDES;
2213 const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode();
2214 if( (eMode == SHOWWINDOWMODE_END) || (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) )
2216 mpShowWindow->RestartShow( nPageNumber );
2218 else if( nPageNumber != mpSlideController->getCurrentSlideNumber() )
2220 displaySlideNumber( nPageNumber );
2222 mbWasPaused = false;
2225 return false;
2228 Reference< XSlideShow > SlideshowImpl::createSlideShow()
2230 Reference< XSlideShow > xShow;
2234 Reference< uno::XComponentContext > xContext =
2235 ::comphelper::getProcessComponentContext();
2237 xShow.set( presentation::SlideShow::create(xContext), UNO_SET_THROW );
2239 catch( uno::Exception& )
2241 SAL_WARN( "sd", "sd::SlideshowImpl::createSlideShow(), exception caught: "
2242 << exceptionToString( cppu::getCaughtException() ) );
2245 return xShow;
2248 void SlideshowImpl::createSlideList( bool bAll, const OUString& rPresSlide )
2250 const sal_uInt16 nSlideCount = mpDoc->GetSdPageCount( PageKind::Standard );
2252 if( !nSlideCount )
2253 return;
2255 SdCustomShow* pCustomShow;
2257 if( mpDoc->GetCustomShowList() && maPresSettings.mbCustomShow )
2258 pCustomShow = mpDoc->GetCustomShowList()->GetCurObject();
2259 else
2260 pCustomShow = nullptr;
2262 // create animation slide controller
2263 AnimationSlideController::Mode eMode =
2264 ( pCustomShow && !pCustomShow->PagesVector().empty() ) ? AnimationSlideController::CUSTOM :
2265 (bAll ? AnimationSlideController::ALL : AnimationSlideController::FROM);
2267 Reference< XDrawPagesSupplier > xDrawPages( mpDoc->getUnoModel(), UNO_QUERY_THROW );
2268 Reference< XIndexAccess > xSlides( xDrawPages->getDrawPages(), UNO_QUERY_THROW );
2269 mpSlideController.reset( new AnimationSlideController( xSlides, eMode ) );
2271 if( eMode != AnimationSlideController::CUSTOM )
2273 sal_Int32 nFirstVisibleSlide = 0;
2275 // normal presentation
2276 if( !rPresSlide.isEmpty() )
2278 sal_Int32 nSlide;
2279 bool bTakeNextAvailable = false;
2281 for( nSlide = 0, nFirstVisibleSlide = -1;
2282 ( nSlide < nSlideCount ) && ( -1 == nFirstVisibleSlide ); nSlide++ )
2284 SdPage* pTestSlide = mpDoc->GetSdPage( static_cast<sal_uInt16>(nSlide), PageKind::Standard );
2286 if( pTestSlide->GetName() == rPresSlide )
2288 if( pTestSlide->IsExcluded() )
2289 bTakeNextAvailable = true;
2290 else
2291 nFirstVisibleSlide = nSlide;
2293 else if( bTakeNextAvailable && !pTestSlide->IsExcluded() )
2294 nFirstVisibleSlide = nSlide;
2297 if( -1 == nFirstVisibleSlide )
2298 nFirstVisibleSlide = 0;
2301 for( sal_Int32 i = 0; i < nSlideCount; i++ )
2303 bool bVisible = ! mpDoc->GetSdPage( static_cast<sal_uInt16>(i), PageKind::Standard )->IsExcluded();
2304 if( bVisible || (eMode == AnimationSlideController::ALL) )
2305 mpSlideController->insertSlideNumber( i, bVisible );
2308 mpSlideController->setStartSlideNumber( nFirstVisibleSlide );
2310 else
2312 if( meAnimationMode != ANIMATIONMODE_SHOW && !rPresSlide.isEmpty() )
2314 sal_Int32 nSlide;
2315 for( nSlide = 0; nSlide < nSlideCount; nSlide++ )
2316 if( rPresSlide == mpDoc->GetSdPage( static_cast<sal_uInt16>(nSlide), PageKind::Standard )->GetName() )
2317 break;
2319 if( nSlide < nSlideCount )
2320 mpSlideController->insertSlideNumber( static_cast<sal_uInt16>(nSlide) );
2323 for( const auto& rpPage : pCustomShow->PagesVector() )
2325 const sal_uInt16 nSdSlide = ( rpPage->GetPageNum() - 1 ) / 2;
2327 if( ! mpDoc->GetSdPage( nSdSlide, PageKind::Standard )->IsExcluded())
2328 mpSlideController->insertSlideNumber( nSdSlide );
2333 typedef sal_uInt16 (*FncGetChildWindowId)();
2335 static const FncGetChildWindowId aShowChildren[] =
2337 &AnimationChildWindow::GetChildWindowId,
2338 &Svx3DChildWindow::GetChildWindowId,
2339 &SvxFontWorkChildWindow::GetChildWindowId,
2340 &SvxColorChildWindow::GetChildWindowId,
2341 &SvxSearchDialogWrapper::GetChildWindowId,
2342 &SvxBmpMaskChildWindow::GetChildWindowId,
2343 &SvxIMapDlgChildWindow::GetChildWindowId,
2344 &SvxHlinkDlgWrapper::GetChildWindowId,
2345 &SfxInfoBarContainerChild::GetChildWindowId
2348 void SlideshowImpl::hideChildWindows()
2350 mnChildMask = 0;
2352 if( ANIMATIONMODE_SHOW != meAnimationMode )
2353 return;
2355 SfxViewFrame* pViewFrame = getViewFrame();
2357 if( !pViewFrame )
2358 return;
2360 for( sal_uLong i = 0; i < SAL_N_ELEMENTS( aShowChildren ); i++ )
2362 const sal_uInt16 nId = ( *aShowChildren[ i ] )();
2364 if( pViewFrame->GetChildWindow( nId ) )
2366 pViewFrame->SetChildWindow( nId, false );
2367 mnChildMask |= 1 << i;
2372 void SlideshowImpl::showChildWindows()
2374 if( ANIMATIONMODE_SHOW == meAnimationMode )
2376 SfxViewFrame* pViewFrame = getViewFrame();
2377 if( pViewFrame )
2379 for( sal_uLong i = 0; i < SAL_N_ELEMENTS(aShowChildren); i++ )
2381 if( mnChildMask & ( 1 << i ) )
2382 pViewFrame->SetChildWindow( ( *aShowChildren[ i ] )(), true );
2388 SfxViewFrame* SlideshowImpl::getViewFrame() const
2390 return mpViewShell ? mpViewShell->GetViewFrame() : nullptr;
2393 SfxDispatcher* SlideshowImpl::getDispatcher() const
2395 return (mpViewShell && mpViewShell->GetViewFrame()) ? mpViewShell->GetViewFrame()->GetDispatcher() : nullptr;
2398 SfxBindings* SlideshowImpl::getBindings() const
2400 return (mpViewShell && mpViewShell->GetViewFrame()) ? &mpViewShell->GetViewFrame()->GetBindings() : nullptr;
2403 void SlideshowImpl::resize( const Size& rSize )
2405 maPresSize = rSize;
2407 if(mpShowWindow)
2409 mpShowWindow->SetSizePixel( maPresSize );
2410 mpShowWindow->Show();
2413 if( mxView.is() ) try
2415 awt::WindowEvent aEvt;
2416 mxView->windowResized(aEvt);
2418 catch( Exception& )
2420 SAL_WARN( "sd", "sd::SlideshowImpl::resize(), exception caught: "
2421 << exceptionToString( cppu::getCaughtException() ) );
2425 void SlideshowImpl::setActiveXToolbarsVisible( bool bVisible )
2427 // in case of ActiveX control the toolbars should not be visible if slide show runs in window mode
2428 // actually it runs always in window mode in case of ActiveX control
2429 if ( !(!maPresSettings.mbFullScreen && mpDocSh && mpDocSh->GetMedium()) )
2430 return;
2432 const SfxBoolItem* pItem = SfxItemSet::GetItem<SfxBoolItem>(mpDocSh->GetMedium()->GetItemSet(), SID_VIEWONLY, false);
2433 if ( !(pItem && pItem->GetValue()) )
2434 return;
2436 // this is a plugin/activex mode, no toolbars should be visible during slide show
2437 // after the end of slide show they should be visible again
2438 SfxViewFrame* pViewFrame = getViewFrame();
2439 if( !pViewFrame )
2440 return;
2444 Reference< frame::XLayoutManager > xLayoutManager;
2445 Reference< beans::XPropertySet > xFrameProps( pViewFrame->GetFrame().GetFrameInterface(), UNO_QUERY_THROW );
2446 if ( ( xFrameProps->getPropertyValue( "LayoutManager" )
2447 >>= xLayoutManager )
2448 && xLayoutManager.is() )
2450 xLayoutManager->setVisible( bVisible );
2453 catch( uno::Exception& )
2457 void SAL_CALL SlideshowImpl::activate()
2459 SolarMutexGuard aSolarGuard;
2461 maDeactivateTimer.Stop();
2463 if( !(!mbActive && mxShow.is()) )
2464 return;
2466 mbActive = true;
2468 if( ANIMATIONMODE_SHOW == meAnimationMode )
2470 if( mbAutoSaveWasOn )
2471 setAutoSaveState( false );
2473 if( mpShowWindow )
2475 SfxViewFrame* pViewFrame = getViewFrame();
2476 SfxDispatcher* pDispatcher = pViewFrame ? pViewFrame->GetDispatcher() : nullptr;
2478 hideChildWindows();
2480 if( pDispatcher )
2482 // filter all forbidden slots
2483 pDispatcher->SetSlotFilter( SfxSlotFilterState::ENABLED, pAllowed );
2486 if( getBindings() )
2487 getBindings()->InvalidateAll(true);
2489 mpShowWindow->GrabFocus();
2493 resume();
2496 void SAL_CALL SlideshowImpl::deactivate()
2498 SolarMutexGuard aSolarGuard;
2500 if( mbActive && mxShow.is() )
2502 maDeactivateTimer.Start();
2506 IMPL_LINK_NOARG(SlideshowImpl, deactivateHdl, Timer *, void)
2508 if( !(mbActive && mxShow.is()) )
2509 return;
2511 mbActive = false;
2513 pause();
2515 if( ANIMATIONMODE_SHOW == meAnimationMode )
2517 if( mbAutoSaveWasOn )
2518 setAutoSaveState( true );
2520 if( mpShowWindow )
2522 showChildWindows();
2527 sal_Bool SAL_CALL SlideshowImpl::isActive()
2529 SolarMutexGuard aSolarGuard;
2530 return mbActive;
2533 void SlideshowImpl::setAutoSaveState( bool bOn)
2537 uno::Reference<uno::XComponentContext> xContext( ::comphelper::getProcessComponentContext() );
2539 uno::Reference< util::XURLTransformer > xParser(util::URLTransformer::create(xContext));
2540 util::URL aURL;
2541 aURL.Complete = "vnd.sun.star.autorecovery:/setAutoSaveState";
2542 xParser->parseStrict(aURL);
2544 Sequence< beans::PropertyValue > aArgs(1);
2545 aArgs[0].Name = "AutoSaveState";
2546 aArgs[0].Value <<= bOn;
2548 uno::Reference< frame::XDispatch > xAutoSave = frame::theAutoRecovery::get(xContext);
2549 xAutoSave->dispatch(aURL, aArgs);
2551 catch( Exception& )
2553 OSL_FAIL("sd::SlideshowImpl::setAutoSaveState(), exception caught!");
2557 Reference< XDrawPage > SAL_CALL SlideshowImpl::getCurrentSlide()
2559 SolarMutexGuard aSolarGuard;
2561 Reference< XDrawPage > xSlide;
2562 if( mxShow.is() && mpSlideController.get() )
2564 sal_Int32 nSlide = getCurrentSlideNumber();
2565 if( (nSlide >= 0) && (nSlide < mpSlideController->getSlideNumberCount() ) )
2566 xSlide = mpSlideController->getSlideByNumber( nSlide );
2569 return xSlide;
2572 sal_Int32 SAL_CALL SlideshowImpl::getNextSlideIndex()
2574 SolarMutexGuard aSolarGuard;
2576 if( mxShow.is() )
2578 return mpSlideController->getNextSlideIndex();
2580 else
2582 return -1;
2586 sal_Int32 SAL_CALL SlideshowImpl::getCurrentSlideIndex()
2588 return mpSlideController.get() ? mpSlideController->getCurrentSlideIndex() : -1;
2591 // css::presentation::XSlideShowController:
2593 ::sal_Int32 SAL_CALL SlideshowImpl::getSlideCount()
2595 return mpSlideController.get() ? mpSlideController->getSlideIndexCount() : 0;
2598 Reference< XDrawPage > SAL_CALL SlideshowImpl::getSlideByIndex(::sal_Int32 Index)
2600 if ((mpSlideController == nullptr) || (Index < 0)
2601 || (Index >= mpSlideController->getSlideIndexCount()))
2602 throw IndexOutOfBoundsException();
2604 return mpSlideController->getSlideByNumber( mpSlideController->getSlideNumber( Index ) );
2607 sal_Bool SAL_CALL SlideshowImpl::getAlwaysOnTop()
2609 SolarMutexGuard aSolarGuard;
2610 return maPresSettings.mbAlwaysOnTop;
2613 void SAL_CALL SlideshowImpl::setAlwaysOnTop( sal_Bool bAlways )
2615 SolarMutexGuard aSolarGuard;
2616 if( maPresSettings.mbAlwaysOnTop != bool(bAlways) )
2618 maPresSettings.mbAlwaysOnTop = bAlways;
2619 // todo, can this be changed while running?
2623 sal_Bool SAL_CALL SlideshowImpl::isFullScreen()
2625 SolarMutexGuard aSolarGuard;
2626 return maPresSettings.mbFullScreen;
2629 sal_Bool SAL_CALL SlideshowImpl::getMouseVisible()
2631 SolarMutexGuard aSolarGuard;
2632 return maPresSettings.mbMouseVisible;
2635 void SAL_CALL SlideshowImpl::setMouseVisible( sal_Bool bVisible )
2637 SolarMutexGuard aSolarGuard;
2638 if( maPresSettings.mbMouseVisible != bool(bVisible) )
2640 maPresSettings.mbMouseVisible = bVisible;
2641 if( mpShowWindow )
2642 mpShowWindow->SetMouseAutoHide( !maPresSettings.mbMouseVisible );
2646 sal_Bool SAL_CALL SlideshowImpl::getUsePen()
2648 SolarMutexGuard aSolarGuard;
2649 return mbUsePen;
2652 void SAL_CALL SlideshowImpl::setUsePen( sal_Bool bMouseAsPen )
2654 SolarMutexGuard aSolarGuard;
2655 mbUsePen = bMouseAsPen;
2656 if( !mxShow.is() )
2657 return;
2661 // For Pencolor;
2662 Any aValue;
2663 if( mbUsePen )
2664 aValue <<= mnUserPaintColor;
2665 beans::PropertyValue aPenProp;
2666 aPenProp.Name = "UserPaintColor";
2667 aPenProp.Value = aValue;
2668 mxShow->setProperty( aPenProp );
2670 //for StrokeWidth :
2671 if( mbUsePen )
2673 beans::PropertyValue aPenPropWidth;
2674 aPenPropWidth.Name = "UserPaintStrokeWidth";
2675 aPenPropWidth.Value <<= mdUserPaintStrokeWidth;
2676 mxShow->setProperty( aPenPropWidth );
2678 // for Pen Mode
2679 beans::PropertyValue aPenPropSwitchPenMode;
2680 aPenPropSwitchPenMode.Name = "SwitchPenMode";
2681 aPenPropSwitchPenMode.Value <<= true;
2682 mxShow->setProperty( aPenPropSwitchPenMode );
2685 catch( Exception& )
2687 SAL_WARN( "sd", "sd::SlideshowImpl::setUsePen(), exception caught: "
2688 << exceptionToString( cppu::getCaughtException() ) );
2692 double SAL_CALL SlideshowImpl::getPenWidth()
2694 SolarMutexGuard aSolarGuard;
2695 return mdUserPaintStrokeWidth;
2698 void SAL_CALL SlideshowImpl::setPenWidth( double dStrokeWidth )
2700 SolarMutexGuard aSolarGuard;
2701 mdUserPaintStrokeWidth = dStrokeWidth;
2702 setUsePen( true ); // enable pen mode, update color and width
2705 sal_Int32 SAL_CALL SlideshowImpl::getPenColor()
2707 SolarMutexGuard aSolarGuard;
2708 return mnUserPaintColor;
2711 void SAL_CALL SlideshowImpl::setPenColor( sal_Int32 nColor )
2713 SolarMutexGuard aSolarGuard;
2714 mnUserPaintColor = nColor;
2715 setUsePen( true ); // enable pen mode, update color
2718 void SlideshowImpl::setEraseAllInk(bool bEraseAllInk)
2720 if( !bEraseAllInk )
2721 return;
2723 SolarMutexGuard aSolarGuard;
2724 if( !mxShow.is() )
2725 return;
2729 beans::PropertyValue aPenPropEraseAllInk;
2730 aPenPropEraseAllInk.Name = "EraseAllInk";
2731 aPenPropEraseAllInk.Value <<= bEraseAllInk;
2732 mxShow->setProperty( aPenPropEraseAllInk );
2734 catch( Exception& )
2736 SAL_WARN( "sd.slideshow", "sd::SlideshowImpl::setEraseAllInk(), "
2737 "exception caught: " << exceptionToString( cppu::getCaughtException() ));
2741 // XSlideShowController Methods
2742 sal_Bool SAL_CALL SlideshowImpl::isRunning( )
2744 SolarMutexGuard aSolarGuard;
2745 return mxShow.is();
2748 void SAL_CALL SlideshowImpl::gotoNextEffect( )
2750 SolarMutexGuard aSolarGuard;
2752 if( !(mxShow.is() && mpSlideController.get() && mpShowWindow) )
2753 return;
2755 if( mbIsPaused )
2756 resume();
2758 const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode();
2759 if( eMode == SHOWWINDOWMODE_END )
2761 endPresentation();
2763 else if( (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) )
2765 mpShowWindow->RestartShow();
2767 else
2769 mxShow->nextEffect();
2770 update();
2774 void SAL_CALL SlideshowImpl::gotoPreviousEffect( )
2776 SolarMutexGuard aSolarGuard;
2778 if( !(mxShow.is() && mpSlideController.get() && mpShowWindow) )
2779 return;
2781 if( mbIsPaused )
2782 resume();
2784 const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode();
2785 if( (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) )
2787 mpShowWindow->RestartShow();
2789 else
2791 mxShow->previousEffect();
2792 update();
2796 void SAL_CALL SlideshowImpl::gotoFirstSlide( )
2798 SolarMutexGuard aSolarGuard;
2800 if( !(mpShowWindow && mpSlideController.get()) )
2801 return;
2803 if( mbIsPaused )
2804 resume();
2806 if( mpShowWindow->GetShowWindowMode() == SHOWWINDOWMODE_END )
2808 if( mpSlideController->getSlideIndexCount() )
2809 mpShowWindow->RestartShow( 0);
2811 else
2813 displaySlideIndex( 0 );
2817 void SAL_CALL SlideshowImpl::gotoNextSlide( )
2819 SolarMutexGuard aSolarGuard;
2821 if( mbIsPaused )
2822 resume();
2824 const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode();
2825 if( (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) )
2827 mpShowWindow->RestartShow();
2829 else
2831 // if this is a show, ignore user inputs and
2832 // start 20ms timer to reenable inputs to filter
2833 // buffered inputs during slide transition
2834 if( meAnimationMode == ANIMATIONMODE_SHOW )
2836 mbInputFreeze = true;
2837 maInputFreezeTimer.Start();
2840 if( mpSlideController.get() )
2842 if( mpSlideController->nextSlide() )
2844 displayCurrentSlide();
2846 else
2848 stopSound();
2850 if( meAnimationMode == ANIMATIONMODE_PREVIEW )
2852 endPresentation();
2854 else if( maPresSettings.mbEndless )
2856 if( maPresSettings.mnPauseTimeout )
2858 if( mpShowWindow )
2860 if ( maPresSettings.mbShowPauseLogo )
2862 Graphic aGraphic(SfxApplication::GetApplicationLogo(360));
2863 mpShowWindow->SetPauseMode( maPresSettings.mnPauseTimeout, &aGraphic );
2865 else
2866 mpShowWindow->SetPauseMode( maPresSettings.mnPauseTimeout );
2869 else
2871 displaySlideIndex( 0 );
2874 else
2876 if( mpShowWindow )
2878 mpShowWindow->SetEndMode();
2879 if( !mpViewShell->GetDoc()->IsStartWithPresentation() )
2880 pause();
2888 void SAL_CALL SlideshowImpl::gotoPreviousSlide( )
2890 gotoPreviousSlide(false);
2893 void SlideshowImpl::gotoPreviousSlide (const bool bSkipAllMainSequenceEffects)
2895 SolarMutexGuard aSolarGuard;
2897 if( !(mxShow.is() && mpSlideController.get()) )
2898 return;
2902 if( mbIsPaused )
2903 resume();
2905 const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode();
2906 if( eMode == SHOWWINDOWMODE_END )
2908 mpShowWindow->RestartShow( mpSlideController->getCurrentSlideIndex() );
2910 else if( (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) )
2912 mpShowWindow->RestartShow();
2914 else
2916 if( mpSlideController->previousSlide())
2917 displayCurrentSlide(bSkipAllMainSequenceEffects);
2918 else if (bSkipAllMainSequenceEffects)
2920 // We could not go to the previous slide (probably because
2921 // the current slide is already the first one). We still
2922 // have to call displayCurrentSlide because the calling
2923 // slideshow can not determine whether there is a previous
2924 // slide or not and has already prepared for a slide change.
2925 // This slide change has to be completed now, even when
2926 // changing to the same slide.
2927 // Note that in this special case we do NOT pass
2928 // bSkipAllMainSequenceEffects because we display the same
2929 // slide as before and do not want to show all its effects.
2930 displayCurrentSlide();
2934 catch( Exception& )
2936 SAL_WARN( "sd", "sd::SlideshowImpl::gotoPreviousSlide(), exception caught: "
2937 << exceptionToString( cppu::getCaughtException() ) );
2941 void SAL_CALL SlideshowImpl::gotoLastSlide()
2943 SolarMutexGuard aSolarGuard;
2945 if( !mpSlideController.get() )
2946 return;
2948 if( mbIsPaused )
2949 resume();
2951 const sal_Int32 nLastSlideIndex = mpSlideController->getSlideIndexCount() - 1;
2952 if( nLastSlideIndex >= 0 )
2954 if( mpShowWindow->GetShowWindowMode() == SHOWWINDOWMODE_END )
2956 mpShowWindow->RestartShow( nLastSlideIndex );
2958 else
2960 displaySlideIndex( nLastSlideIndex );
2965 void SAL_CALL SlideshowImpl::gotoBookmark( const OUString& rBookmark )
2967 SolarMutexGuard aSolarGuard;
2969 if( mbIsPaused )
2970 resume();
2972 sal_Int32 nSlideNumber = getSlideNumberForBookmark( rBookmark );
2973 if( nSlideNumber != -1 )
2974 displaySlideNumber( nSlideNumber );
2977 void SAL_CALL SlideshowImpl::gotoSlide( const Reference< XDrawPage >& xSlide )
2979 SolarMutexGuard aSolarGuard;
2981 if( !(mpSlideController.get() && xSlide.is()) )
2982 return;
2984 if( mbIsPaused )
2985 resume();
2987 const sal_Int32 nSlideCount = mpSlideController->getSlideNumberCount();
2988 for( sal_Int32 nSlide = 0; nSlide < nSlideCount; nSlide++ )
2990 if( mpSlideController->getSlideByNumber( nSlide ) == xSlide )
2992 displaySlideNumber( nSlide );
2997 void SAL_CALL SlideshowImpl::gotoSlideIndex( sal_Int32 nIndex )
2999 SolarMutexGuard aSolarGuard;
3001 if( mbIsPaused )
3002 resume();
3004 displaySlideIndex( nIndex );
3007 void SAL_CALL SlideshowImpl::stopSound( )
3009 SolarMutexGuard aSolarGuard;
3013 if( mxPlayer.is() )
3015 mxPlayer->stop();
3016 mxPlayer.clear();
3019 catch( Exception& )
3021 SAL_WARN( "sd", "sd::SlideshowImpl::stopSound(), exception caught: "
3022 << exceptionToString( cppu::getCaughtException() ) );
3026 // XIndexAccess
3028 ::sal_Int32 SAL_CALL SlideshowImpl::getCount( )
3030 return getSlideCount();
3033 css::uno::Any SAL_CALL SlideshowImpl::getByIndex( ::sal_Int32 Index )
3035 return Any( getSlideByIndex( Index ) );
3038 css::uno::Type SAL_CALL SlideshowImpl::getElementType( )
3040 return cppu::UnoType<XDrawPage>::get();
3043 sal_Bool SAL_CALL SlideshowImpl::hasElements( )
3045 return getSlideCount() != 0;
3048 Reference< XSlideShow > SAL_CALL SlideshowImpl::getSlideShow()
3050 return mxShow;
3053 PresentationSettingsEx::PresentationSettingsEx( const PresentationSettingsEx& r )
3054 : PresentationSettings( r )
3055 , mbRehearseTimings(r.mbRehearseTimings)
3056 , mbPreview(r.mbPreview)
3057 , mpParentWindow( nullptr )
3061 PresentationSettingsEx::PresentationSettingsEx( PresentationSettings const & r )
3062 : PresentationSettings( r )
3063 , mbRehearseTimings(false)
3064 , mbPreview(false)
3065 , mpParentWindow(nullptr)
3069 void PresentationSettingsEx::SetArguments( const Sequence< PropertyValue >& rArguments )
3071 sal_Int32 nArguments = rArguments.getLength();
3072 const PropertyValue* pValue = rArguments.getConstArray();
3074 while( nArguments-- )
3076 SetPropertyValue( pValue->Name, pValue->Value );
3077 pValue++;
3081 void PresentationSettingsEx::SetPropertyValue( const OUString& rProperty, const Any& rValue )
3083 if ( rProperty == "RehearseTimings" )
3085 if( rValue >>= mbRehearseTimings )
3086 return;
3088 else if ( rProperty == "Preview" )
3090 if( rValue >>= mbPreview )
3091 return;
3093 else if ( rProperty == "AnimationNode" )
3095 if( rValue >>= mxAnimationNode )
3096 return;
3098 else if ( rProperty == "ParentWindow" )
3100 Reference< XWindow > xWindow;
3101 if( rValue >>= xWindow )
3103 mpParentWindow = xWindow.is() ? VCLUnoHelper::GetWindow( xWindow )
3104 : VclPtr<vcl::Window>();
3105 return;
3108 else if ( rProperty == "AllowAnimations" )
3110 if( rValue >>= mbAnimationAllowed )
3111 return;
3113 else if ( rProperty == "FirstPage" )
3115 OUString aPresPage;
3116 if( rValue >>= aPresPage )
3118 maPresPage = getUiNameFromPageApiNameImpl(aPresPage);
3119 mbCustomShow = false;
3120 mbAll = false;
3121 return;
3123 else
3125 if( rValue >>= mxStartPage )
3126 return;
3129 else if ( rProperty == "IsAlwaysOnTop" )
3131 if( rValue >>= mbAlwaysOnTop )
3132 return;
3134 else if ( rProperty == "IsAutomatic" )
3136 if( rValue >>= mbManual )
3137 return;
3139 else if ( rProperty == "IsEndless" )
3141 if( rValue >>= mbEndless )
3142 return;
3144 else if ( rProperty == "IsFullScreen" )
3146 if( rValue >>= mbFullScreen )
3147 return;
3149 else if ( rProperty == "IsMouseVisible" )
3151 if( rValue >>= mbMouseVisible )
3152 return;
3154 else if ( rProperty == "Pause" )
3156 sal_Int32 nPause = -1;
3157 if( (rValue >>= nPause) && (nPause >= 0) )
3159 mnPauseTimeout = nPause;
3160 return;
3163 else if ( rProperty == "UsePen" )
3165 if( rValue >>= mbMouseAsPen )
3166 return;
3168 throw IllegalArgumentException();
3171 // XAnimationListener
3173 SlideShowListenerProxy::SlideShowListenerProxy( const rtl::Reference< SlideshowImpl >& xController, const css::uno::Reference< css::presentation::XSlideShow >& xSlideShow )
3174 : maListeners( m_aMutex )
3175 , mxController( xController )
3176 , mxSlideShow( xSlideShow )
3180 SlideShowListenerProxy::~SlideShowListenerProxy()
3184 void SlideShowListenerProxy::addAsSlideShowListener()
3186 if( mxSlideShow.is() )
3188 Reference< XSlideShowListener > xSlideShowListener( this );
3189 mxSlideShow->addSlideShowListener( xSlideShowListener );
3193 void SlideShowListenerProxy::removeAsSlideShowListener()
3195 if( mxSlideShow.is() )
3197 Reference< XSlideShowListener > xSlideShowListener( this );
3198 mxSlideShow->removeSlideShowListener( xSlideShowListener );
3202 void SlideShowListenerProxy::addShapeEventListener( const css::uno::Reference< css::drawing::XShape >& xShape )
3204 if( mxSlideShow.is() )
3206 Reference< XShapeEventListener > xListener( this );
3207 mxSlideShow->addShapeEventListener( xListener, xShape );
3211 void SlideShowListenerProxy::removeShapeEventListener( const css::uno::Reference< css::drawing::XShape >& xShape )
3213 if( mxSlideShow.is() )
3215 Reference< XShapeEventListener > xListener( this );
3216 mxSlideShow->removeShapeEventListener( xListener, xShape );
3220 void SlideShowListenerProxy::addSlideShowListener( const css::uno::Reference< css::presentation::XSlideShowListener >& xListener )
3222 maListeners.addInterface(xListener);
3225 void SlideShowListenerProxy::removeSlideShowListener( const css::uno::Reference< css::presentation::XSlideShowListener >& xListener )
3227 maListeners.removeInterface(xListener);
3230 void SAL_CALL SlideShowListenerProxy::beginEvent( const Reference< XAnimationNode >& xNode )
3232 ::osl::MutexGuard aGuard( m_aMutex );
3234 if( maListeners.getLength() >= 0 )
3236 maListeners.forEach<XSlideShowListener>(
3237 [&] (Reference<XAnimationListener> const& xListener) {
3238 return xListener->beginEvent(xNode);
3239 } );
3243 void SAL_CALL SlideShowListenerProxy::endEvent( const Reference< XAnimationNode >& xNode )
3245 ::osl::MutexGuard aGuard( m_aMutex );
3247 if( maListeners.getLength() >= 0 )
3249 maListeners.forEach<XSlideShowListener>(
3250 [&] (Reference<XAnimationListener> const& xListener) {
3251 return xListener->endEvent(xNode);
3252 } );
3256 void SAL_CALL SlideShowListenerProxy::repeat( const Reference< XAnimationNode >& xNode, ::sal_Int32 nRepeat )
3258 ::osl::MutexGuard aGuard( m_aMutex );
3260 if( maListeners.getLength() >= 0 )
3262 maListeners.forEach<XSlideShowListener>(
3263 [&] (Reference<XAnimationListener> const& xListener) {
3264 return xListener->repeat(xNode, nRepeat);
3265 } );
3269 // css::presentation::XSlideShowListener:
3271 void SAL_CALL SlideShowListenerProxy::paused( )
3273 ::osl::MutexGuard aGuard( m_aMutex );
3275 maListeners.forEach<XSlideShowListener>(
3276 [](uno::Reference<presentation::XSlideShowListener> const& xListener)
3278 xListener->paused();
3282 void SAL_CALL SlideShowListenerProxy::resumed( )
3284 ::osl::MutexGuard aGuard( m_aMutex );
3286 maListeners.forEach<XSlideShowListener>(
3287 [](uno::Reference<presentation::XSlideShowListener> const& xListener)
3289 xListener->resumed();
3293 void SAL_CALL SlideShowListenerProxy::slideTransitionStarted( )
3295 ::osl::MutexGuard aGuard( m_aMutex );
3297 maListeners.forEach<XSlideShowListener>(
3298 [](uno::Reference<presentation::XSlideShowListener> const& xListener)
3300 xListener->slideTransitionStarted();
3304 void SAL_CALL SlideShowListenerProxy::slideTransitionEnded( )
3306 ::osl::MutexGuard aGuard( m_aMutex );
3308 maListeners.forEach<XSlideShowListener>(
3309 [](uno::Reference<presentation::XSlideShowListener> const& xListener)
3311 xListener->slideTransitionEnded ();
3315 void SAL_CALL SlideShowListenerProxy::slideAnimationsEnded( )
3317 ::osl::MutexGuard aGuard( m_aMutex );
3319 maListeners.forEach<XSlideShowListener>(
3320 [](uno::Reference<presentation::XSlideShowListener> const& xListener)
3322 xListener->slideAnimationsEnded ();
3326 void SlideShowListenerProxy::slideEnded(sal_Bool bReverse)
3329 ::osl::MutexGuard aGuard( m_aMutex );
3331 if( maListeners.getLength() >= 0 )
3333 maListeners.forEach<XSlideShowListener>(
3334 [&] (Reference<XSlideShowListener> const& xListener) {
3335 return xListener->slideEnded(bReverse);
3336 } );
3341 SolarMutexGuard aSolarGuard;
3342 if( mxController.is() )
3343 mxController->slideEnded(bReverse);
3347 void SlideShowListenerProxy::hyperLinkClicked( OUString const& aHyperLink )
3350 ::osl::MutexGuard aGuard( m_aMutex );
3352 if( maListeners.getLength() >= 0 )
3354 maListeners.forEach<XSlideShowListener>(
3355 [&] (Reference<XSlideShowListener> const& xListener) {
3356 return xListener->hyperLinkClicked(aHyperLink);
3357 } );
3362 SolarMutexGuard aSolarGuard;
3363 if( mxController.is() )
3364 mxController->hyperLinkClicked(aHyperLink);
3368 // XEventListener
3370 void SAL_CALL SlideShowListenerProxy::disposing( const css::lang::EventObject& aDisposeEvent )
3372 maListeners.disposeAndClear( aDisposeEvent );
3373 mxController.clear();
3374 mxSlideShow.clear();
3377 // XShapeEventListener
3379 void SAL_CALL SlideShowListenerProxy::click( const Reference< XShape >& xShape, const css::awt::MouseEvent& /*aOriginalEvent*/ )
3381 SolarMutexGuard aSolarGuard;
3382 if( mxController.is() )
3383 mxController->click(xShape );
3386 } // namespace ::sd
3388 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */