Update git submodules
[LibreOffice.git] / sd / source / ui / slideshow / slideshowimpl.cxx
bloba9f16b86b8d4567c8882a8b13293b7e2ada86edf
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/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 <officecfg/Office/Common.hxx>
41 #include <svl/stritem.hxx>
42 #include <svl/urihelper.hxx>
43 #include <basic/sbstar.hxx>
45 #include <toolkit/helper/vclunohelper.hxx>
46 #include <comphelper/diagnose_ex.hxx>
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/svdoole2.hxx>
54 #include <svx/f3dchild.hxx>
55 #include <svx/imapdlg.hxx>
56 #include <svx/fontwork.hxx>
57 #include <svx/SvxColorChildWindow.hxx>
58 #include <svx/bmpmask.hxx>
59 #include <svx/srchdlg.hxx>
60 #include <svx/hyperdlg.hxx>
61 #include <svx/svxids.hrc>
62 #include <AnimationChildWindow.hxx>
63 #include <notifydocumentevent.hxx>
64 #include "slideshowimpl.hxx"
65 #include "slideshowviewimpl.hxx"
66 #include "PaneHider.hxx"
68 #include <bitmaps.hlst>
69 #include <strings.hrc>
70 #include <sdresid.hxx>
71 #include <utility>
72 #include <vcl/canvastools.hxx>
73 #include <vcl/commandevent.hxx>
74 #include <vcl/weldutils.hxx>
76 #include <vcl/settings.hxx>
77 #include <vcl/svapp.hxx>
78 #include <vcl/help.hxx>
79 #include <comphelper/processfactory.hxx>
80 #include <comphelper/propertyvalue.hxx>
81 #include <rtl/ref.hxx>
82 #include <o3tl/safeint.hxx>
83 #include <o3tl/string_view.hxx>
84 #include <avmedia/mediawindow.hxx>
85 #include <svtools/colrdlg.hxx>
86 #include <DrawDocShell.hxx>
87 #include <ViewShellBase.hxx>
88 #include <PresentationViewShell.hxx>
89 #include <RemoteServer.hxx>
90 #include <customshowlist.hxx>
91 #include <unopage.hxx>
92 #include <sdpage.hxx>
93 #include <sdmod.hxx>
94 #include <app.hrc>
95 #include <cusshow.hxx>
96 #include <optsitem.hxx>
98 #define CM_SLIDES 21
100 using ::com::sun::star::animations::XAnimationNode;
101 using ::com::sun::star::animations::XAnimationListener;
102 using ::com::sun::star::awt::XWindow;
103 using namespace ::com::sun::star;
104 using namespace ::com::sun::star::lang;
105 using namespace ::com::sun::star::uno;
106 using namespace ::com::sun::star::drawing;
107 using namespace ::com::sun::star::container;
108 using namespace ::com::sun::star::document;
109 using namespace ::com::sun::star::presentation;
110 using namespace ::com::sun::star::beans;
112 namespace sd
114 /** Slots, which will be disabled in the slide show and are managed by Sfx.
115 Have to be sorted in the order of the SIDs */
116 sal_uInt16 const pAllowed[] =
118 SID_OPENDOC , // 5501 ///< that internally jumps work
119 SID_JUMPTOMARK , // 5598
120 SID_OPENHYPERLINK , // 6676
121 SID_PRESENTATION_END // 27218
124 class AnimationSlideController
126 public:
127 enum Mode { ALL, FROM, CUSTOM, PREVIEW };
129 public:
130 AnimationSlideController( Reference< XIndexAccess > const & xSlides, Mode eMode );
132 void setStartSlideNumber( sal_Int32 nSlideNumber ) { mnStartSlideNumber = nSlideNumber; }
133 sal_Int32 getStartSlideIndex() const;
135 sal_Int32 getCurrentSlideNumber() const;
136 sal_Int32 getCurrentSlideIndex() const;
138 sal_Int32 getSlideIndexCount() const { return maSlideNumbers.size(); }
139 sal_Int32 getSlideNumberCount() const { return mnSlideCount; }
141 sal_Int32 getSlideNumber( sal_Int32 nSlideIndex ) const;
143 void insertSlideNumber( sal_Int32 nSlideNumber, bool bVisible = true );
144 void setPreviewNode( const Reference< XAnimationNode >& xPreviewNode );
146 bool jumpToSlideIndex( sal_Int32 nNewSlideIndex );
147 bool jumpToSlideNumber( sal_Int32 nNewSlideIndex );
149 bool nextSlide();
150 bool previousSlide();
152 void displayCurrentSlide( const Reference< XSlideShow >& xShow,
153 const Reference< XDrawPagesSupplier>& xDrawPages,
154 const bool bSkipAllMainSequenceEffects );
156 sal_Int32 getNextSlideIndex() const;
157 sal_Int32 getPreviousSlideIndex() const;
159 bool isVisibleSlideNumber( sal_Int32 nSlideNumber ) const;
161 Reference< XDrawPage > getSlideByNumber( sal_Int32 nSlideNumber ) const;
163 sal_Int32 getNextSlideNumber() const;
165 bool hasSlides() const { return !maSlideNumbers.empty(); }
167 private:
168 bool getSlideAPI( sal_Int32 nSlideNumber, Reference< XDrawPage >& xSlide, Reference< XAnimationNode >& xAnimNode );
169 sal_Int32 findSlideIndex( sal_Int32 nSlideNumber ) const;
171 bool isValidIndex( sal_Int32 nIndex ) const { return (nIndex >= 0) && (o3tl::make_unsigned(nIndex) < maSlideNumbers.size()); }
172 bool isValidSlideNumber( sal_Int32 nSlideNumber ) const { return (nSlideNumber >= 0) && (nSlideNumber < mnSlideCount); }
174 private:
175 Mode meMode;
176 sal_Int32 mnStartSlideNumber;
177 std::vector< sal_Int32 > maSlideNumbers;
178 std::vector< bool > maSlideVisible;
179 std::vector< bool > maSlideVisited;
180 Reference< XAnimationNode > mxPreviewNode;
181 sal_Int32 mnSlideCount;
182 sal_Int32 mnCurrentSlideIndex;
183 sal_Int32 mnHiddenSlideNumber;
184 Reference< XIndexAccess > mxSlides;
187 Reference< XDrawPage > AnimationSlideController::getSlideByNumber( sal_Int32 nSlideNumber ) const
189 Reference< XDrawPage > xSlide;
190 if( mxSlides.is() && (nSlideNumber >= 0) && (nSlideNumber < mxSlides->getCount()) )
191 mxSlides->getByIndex( nSlideNumber ) >>= xSlide;
192 return xSlide;
195 bool AnimationSlideController::isVisibleSlideNumber( sal_Int32 nSlideNumber ) const
197 sal_Int32 nIndex = findSlideIndex( nSlideNumber );
199 if( nIndex != -1 )
200 return maSlideVisible[ nIndex ];
201 else
202 return false;
205 void AnimationSlideController::setPreviewNode( const Reference< XAnimationNode >& xPreviewNode )
207 mxPreviewNode = xPreviewNode;
210 AnimationSlideController::AnimationSlideController( Reference< XIndexAccess > const & xSlides, Mode eMode )
211 : meMode( eMode )
212 , mnStartSlideNumber(-1)
213 , mnSlideCount( 0 )
214 , mnCurrentSlideIndex(0)
215 , mnHiddenSlideNumber( -1 )
216 , mxSlides( xSlides )
218 if( mxSlides.is() )
219 mnSlideCount = xSlides->getCount();
222 sal_Int32 AnimationSlideController::getStartSlideIndex() const
224 if( mnStartSlideNumber >= 0 )
226 sal_Int32 nIndex;
227 const sal_Int32 nCount = maSlideNumbers.size();
229 for( nIndex = 0; nIndex < nCount; nIndex++ )
231 if( maSlideNumbers[nIndex] == mnStartSlideNumber )
232 return nIndex;
236 return 0;
239 sal_Int32 AnimationSlideController::getCurrentSlideNumber() const
241 if( mnHiddenSlideNumber != -1 )
242 return mnHiddenSlideNumber;
243 else if( !maSlideNumbers.empty() )
244 return maSlideNumbers[mnCurrentSlideIndex];
245 else
246 return 0;
249 sal_Int32 AnimationSlideController::getCurrentSlideIndex() const
251 if( mnHiddenSlideNumber != -1 )
252 return -1;
253 else
254 return mnCurrentSlideIndex;
257 bool AnimationSlideController::jumpToSlideIndex( sal_Int32 nNewSlideIndex )
259 if( isValidIndex( nNewSlideIndex ) )
261 mnCurrentSlideIndex = nNewSlideIndex;
262 mnHiddenSlideNumber = -1;
263 maSlideVisited[mnCurrentSlideIndex] = true;
264 return true;
266 else
268 return false;
272 bool AnimationSlideController::jumpToSlideNumber( sal_Int32 nNewSlideNumber )
274 sal_Int32 nIndex = findSlideIndex( nNewSlideNumber );
275 if( isValidIndex( nIndex ) )
277 return jumpToSlideIndex( nIndex );
279 else if( (nNewSlideNumber >= 0) && (nNewSlideNumber < mnSlideCount) )
281 // jump to a hidden slide
282 mnHiddenSlideNumber = nNewSlideNumber;
283 return true;
285 else
287 return false;
291 sal_Int32 AnimationSlideController::getSlideNumber( sal_Int32 nSlideIndex ) const
293 if( isValidIndex( nSlideIndex ) )
294 return maSlideNumbers[nSlideIndex];
295 else
296 return -1;
299 void AnimationSlideController::insertSlideNumber( sal_Int32 nSlideNumber, bool bVisible /* = true */ )
301 DBG_ASSERT( isValidSlideNumber( nSlideNumber ), "sd::AnimationSlideController::insertSlideNumber(), illegal index" );
302 if( isValidSlideNumber( nSlideNumber ) )
304 maSlideNumbers.push_back( nSlideNumber );
305 maSlideVisible.push_back( bVisible );
306 maSlideVisited.push_back( false );
310 bool AnimationSlideController::getSlideAPI( sal_Int32 nSlideNumber, Reference< XDrawPage >& xSlide, Reference< XAnimationNode >& xAnimNode )
312 if( isValidSlideNumber( nSlideNumber ) ) try
314 xSlide.set( mxSlides->getByIndex(nSlideNumber), UNO_QUERY_THROW );
316 if( meMode == PREVIEW )
318 xAnimNode = mxPreviewNode;
320 else
322 Reference< animations::XAnimationNodeSupplier > xAnimNodeSupplier( xSlide, UNO_QUERY_THROW );
323 xAnimNode = xAnimNodeSupplier->getAnimationNode();
326 return true;
328 catch( Exception& )
330 TOOLS_WARN_EXCEPTION( "sd", "sd::AnimationSlideController::getSlideAPI()" );
333 return false;
336 sal_Int32 AnimationSlideController::findSlideIndex( sal_Int32 nSlideNumber ) const
338 sal_Int32 nIndex;
339 const sal_Int32 nCount = maSlideNumbers.size();
341 for( nIndex = 0; nIndex < nCount; nIndex++ )
343 if( maSlideNumbers[nIndex] == nSlideNumber )
344 return nIndex;
347 return -1;
350 sal_Int32 AnimationSlideController::getNextSlideIndex() const
352 switch( meMode )
354 case ALL:
356 sal_Int32 nNewSlideIndex = mnCurrentSlideIndex + 1;
357 if( isValidIndex( nNewSlideIndex ) )
359 // if the current slide is not excluded, make sure the
360 // next slide is also not excluded.
361 // if the current slide is excluded, we want to go
362 // to the next slide, even if this is also excluded.
363 if( maSlideVisible[mnCurrentSlideIndex] )
365 while( isValidIndex( nNewSlideIndex ) )
367 if( maSlideVisible[nNewSlideIndex] )
368 break;
370 nNewSlideIndex++;
374 return isValidIndex( nNewSlideIndex ) ? nNewSlideIndex : -1;
377 case FROM:
378 case CUSTOM:
379 return mnHiddenSlideNumber == -1 ? mnCurrentSlideIndex + 1 : mnCurrentSlideIndex;
381 default:
382 case PREVIEW:
383 return -1;
388 sal_Int32 AnimationSlideController::getNextSlideNumber() const
390 sal_Int32 nNextSlideIndex = getNextSlideIndex();
391 if( isValidIndex( nNextSlideIndex ) )
393 return maSlideNumbers[nNextSlideIndex];
395 else
397 return -1;
401 bool AnimationSlideController::nextSlide()
403 return jumpToSlideIndex( getNextSlideIndex() );
406 sal_Int32 AnimationSlideController::getPreviousSlideIndex() const
408 sal_Int32 nNewSlideIndex = mnCurrentSlideIndex - 1;
410 switch( meMode )
412 case ALL:
414 // make sure the previous slide is visible
415 // or was already visited
416 while( isValidIndex( nNewSlideIndex ) )
418 if( maSlideVisible[nNewSlideIndex] || maSlideVisited[nNewSlideIndex] )
419 break;
421 nNewSlideIndex--;
424 break;
427 case PREVIEW:
428 return -1;
430 default:
431 break;
434 return nNewSlideIndex;
437 bool AnimationSlideController::previousSlide()
439 return jumpToSlideIndex( getPreviousSlideIndex() );
442 void AnimationSlideController::displayCurrentSlide( const Reference< XSlideShow >& xShow,
443 const Reference< XDrawPagesSupplier>& xDrawPages,
444 const bool bSkipAllMainSequenceEffects )
446 const sal_Int32 nCurrentSlideNumber = getCurrentSlideNumber();
448 if( !(xShow.is() && (nCurrentSlideNumber != -1 )) )
449 return;
451 Reference< XDrawPage > xSlide;
452 Reference< XAnimationNode > xAnimNode;
453 ::std::vector<PropertyValue> aProperties;
455 const sal_Int32 nNextSlideNumber = getNextSlideNumber();
456 if( getSlideAPI( nNextSlideNumber, xSlide, xAnimNode ) )
458 Sequence< Any > aValue{ Any(xSlide), Any(xAnimNode) };
459 aProperties.emplace_back( "Prefetch" ,
461 Any(aValue),
462 PropertyState_DIRECT_VALUE);
464 if (bSkipAllMainSequenceEffects)
466 // Add one property that prevents the slide transition from being
467 // shown (to speed up the transition to the previous slide) and
468 // one to show all main sequence effects so that the user can
469 // continue to undo effects.
470 aProperties.emplace_back( "SkipAllMainSequenceEffects",
472 Any(true),
473 PropertyState_DIRECT_VALUE);
474 aProperties.emplace_back("SkipSlideTransition",
476 Any(true),
477 PropertyState_DIRECT_VALUE);
480 if( getSlideAPI( nCurrentSlideNumber, xSlide, xAnimNode ) )
481 xShow->displaySlide( xSlide, xDrawPages, xAnimNode, comphelper::containerToSequence(aProperties) );
484 constexpr OUStringLiteral gsOnClick( u"OnClick" );
485 constexpr OUStringLiteral gsBookmark( u"Bookmark" );
486 constexpr OUStringLiteral gsVerb( u"Verb" );
488 SlideshowImpl::SlideshowImpl( const Reference< XPresentation2 >& xPresentation, ViewShell* pViewSh, ::sd::View* pView, SdDrawDocument* pDoc, vcl::Window* pParentWindow )
489 : mxModel(pDoc->getUnoModel(),UNO_QUERY_THROW)
490 , maUpdateTimer("SlideShowImpl maUpdateTimer")
491 , maInputFreezeTimer("SlideShowImpl maInputFreezeTimer")
492 , maDeactivateTimer("SlideShowImpl maDeactivateTimer")
493 , mpView(pView)
494 , mpViewShell(pViewSh)
495 , mpDocSh(pDoc->GetDocSh())
496 , mpDoc(pDoc)
497 , mpParentWindow(pParentWindow)
498 , mpShowWindow(nullptr)
499 , mnRestoreSlide(0)
500 , maPresSize( -1, -1 )
501 , meAnimationMode(ANIMATIONMODE_SHOW)
502 , mpOldActiveWindow(nullptr)
503 , mnChildMask( 0 )
504 , mbDisposed(false)
505 , mbAutoSaveWasOn(false)
506 , mbRehearseTimings(false)
507 , mbIsPaused(false)
508 , mbWasPaused(false)
509 , mbInputFreeze(false)
510 , mbActive(false)
511 , maPresSettings( pDoc->getPresentationSettings() )
512 , mnUserPaintColor( 0x80ff0000L )
513 , mbUsePen(false)
514 , mdUserPaintStrokeWidth ( 150.0 )
515 , mnEndShowEvent(nullptr)
516 , mnContextMenuEvent(nullptr)
517 , mxPresentation( xPresentation )
519 if( mpViewShell )
520 mpOldActiveWindow = mpViewShell->GetActiveWindow();
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);
526 maDeactivateTimer.SetInvokeHandler(LINK(this, SlideshowImpl, deactivateHdl));
527 maDeactivateTimer.SetTimeout( 20 );
529 maInputFreezeTimer.SetInvokeHandler( LINK( this, SlideshowImpl, ReadyForNextInputHdl ) );
530 maInputFreezeTimer.SetTimeout( 20 );
532 // no autosave during show
533 if( officecfg::Office::Common::Save::Document::AutoSave::get() )
534 mbAutoSaveWasOn = true;
536 Application::AddEventListener( LINK( this, SlideshowImpl, EventListenerHdl ) );
538 mbUsePen = maPresSettings.mbMouseAsPen;
540 SdOptions* pOptions = SD_MOD()->GetSdOptions(DocumentType::Impress);
541 if( pOptions )
543 mnUserPaintColor = pOptions->GetPresentationPenColor();
544 mdUserPaintStrokeWidth = pOptions->GetPresentationPenWidth();
548 SlideshowImpl::~SlideshowImpl()
550 SdModule *pModule = SD_MOD();
551 //rhbz#806663 SlideshowImpl can outlive SdModule
552 SdOptions* pOptions = pModule ?
553 pModule->GetSdOptions(DocumentType::Impress) : nullptr;
554 if( pOptions )
556 pOptions->SetPresentationPenColor(mnUserPaintColor);
557 pOptions->SetPresentationPenWidth(mdUserPaintStrokeWidth);
560 Application::RemoveEventListener( LINK( this, SlideshowImpl, EventListenerHdl ) );
562 maDeactivateTimer.Stop();
564 if( !mbDisposed )
566 OSL_FAIL("SlideshowImpl::~SlideshowImpl(), component was not disposed!");
567 std::unique_lock g(m_aMutex);
568 disposing(g);
572 void SlideshowImpl::disposing(std::unique_lock<std::mutex>&)
574 #ifdef ENABLE_SDREMOTE
575 RemoteServer::presentationStopped();
576 #endif
577 if( mxShow.is() && mpDoc )
578 NotifyDocumentEvent(
579 *mpDoc,
580 "OnEndPresentation" );
582 if( mbAutoSaveWasOn )
583 setAutoSaveState( true );
585 if( mnEndShowEvent )
586 Application::RemoveUserEvent( mnEndShowEvent );
587 if( mnContextMenuEvent )
588 Application::RemoveUserEvent( mnContextMenuEvent );
590 maInputFreezeTimer.Stop();
592 SolarMutexGuard aSolarGuard;
594 if( !mxShow.is() )
595 return;
597 if( mxPresentation.is() )
598 mxPresentation->end();
600 maUpdateTimer.Stop();
602 removeShapeEvents();
604 if( mxListenerProxy.is() )
605 mxListenerProxy->removeAsSlideShowListener();
609 if( mxView.is() )
610 mxShow->removeView( mxView );
612 Reference< XComponent > xComponent( mxShow, UNO_QUERY );
613 if( xComponent.is() )
614 xComponent->dispose();
616 if( mxView.is() )
617 mxView->dispose();
619 catch( Exception& )
621 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::stop()" );
624 mxShow.clear();
625 mxView.clear();
626 mxListenerProxy.clear();
627 mpSlideController.reset();
629 // take DrawView from presentation window, but give the old window back
630 if( mpShowWindow && mpView )
631 mpView->DeleteDeviceFromPaintView( *mpShowWindow->GetOutDev() );
633 if( mpView )
634 mpView->SetAnimationPause( false );
636 if( mpViewShell )
638 mpViewShell->SetActiveWindow(mpOldActiveWindow);
639 if (mpShowWindow)
640 mpShowWindow->SetViewShell( nullptr );
643 if( mpView )
644 mpView->InvalidateAllWin();
646 if( maPresSettings.mbFullScreen )
648 #if HAVE_FEATURE_SCRIPTING
649 // restore StarBASICErrorHdl
650 StarBASIC::SetGlobalErrorHdl(maStarBASICGlobalErrorHdl);
651 maStarBASICGlobalErrorHdl = Link<StarBASIC*,bool>();
652 #endif
654 else
656 if( mpShowWindow )
657 mpShowWindow->Hide();
660 if( meAnimationMode == ANIMATIONMODE_SHOW )
662 mpDocSh->SetSlotFilter();
663 mpDocSh->ApplySlotFilter();
665 Help::EnableContextHelp();
666 Help::EnableExtHelp();
668 showChildWindows();
669 mnChildMask = 0;
672 // show current window again
673 if( mpViewShell && dynamic_cast< PresentationViewShell *>( mpViewShell ) == nullptr)
675 if( meAnimationMode == ANIMATIONMODE_SHOW )
677 mpViewShell->GetViewShellBase().ShowUIControls (true);
678 mpPaneHider.reset();
680 else if( meAnimationMode == ANIMATIONMODE_PREVIEW )
682 mpViewShell->ShowUIControls(true);
686 if( mpShowWindow )
687 mpShowWindow->Hide();
688 mpShowWindow.disposeAndClear();
690 if ( mpViewShell )
692 if( meAnimationMode == ANIMATIONMODE_SHOW )
694 ::sd::Window* pActWin = mpViewShell->GetActiveWindow();
696 if (pActWin)
698 Size aVisSizePixel = pActWin->GetOutputSizePixel();
699 ::tools::Rectangle aVisAreaWin = pActWin->PixelToLogic( ::tools::Rectangle( Point(0,0), aVisSizePixel) );
700 mpViewShell->VisAreaChanged(aVisAreaWin);
701 if (mpView)
702 mpView->VisAreaChanged(pActWin->GetOutDev());
703 pActWin->GrabFocus();
707 // restart the custom show dialog if he started us
708 if( mpViewShell->IsStartShowWithDialog() && getDispatcher() )
710 mpViewShell->SetStartShowWithDialog( false );
711 getDispatcher()->Execute( SID_CUSTOMSHOW_DLG, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD );
714 mpViewShell->GetViewShellBase().UpdateBorder(true);
717 if( mpShowWindow )
719 mpShowWindow.disposeAndClear();
722 setActiveXToolbarsVisible( true );
724 mbDisposed = true;
727 bool SlideshowImpl::startPreview(
728 const Reference< XDrawPage >& xDrawPage,
729 const Reference< XAnimationNode >& xAnimationNode,
730 vcl::Window * pParent )
732 bool bRet = false;
736 const Reference<lang::XServiceInfo> xServiceInfo( xDrawPage, UNO_QUERY );
737 if (xServiceInfo.is()) {
738 const Sequence<OUString> supportedServices(
739 xServiceInfo->getSupportedServiceNames() );
740 if (comphelper::findValue(supportedServices, "com.sun.star.drawing.MasterPage") != -1) {
741 OSL_FAIL("sd::SlideshowImpl::startPreview() "
742 "not allowed on master page!");
743 return false;
747 mxPreviewDrawPage = xDrawPage;
748 mxPreviewAnimationNode = xAnimationNode;
749 meAnimationMode = ANIMATIONMODE_PREVIEW;
751 maPresSettings.mbAll = false;
752 maPresSettings.mbEndless = false;
753 maPresSettings.mbCustomShow = false;
754 maPresSettings.mbManual = false;
755 maPresSettings.mbMouseVisible = false;
756 maPresSettings.mbMouseAsPen = false;
757 maPresSettings.mbLockedPages = false;
758 maPresSettings.mbAlwaysOnTop = false;
759 maPresSettings.mbUseNavigation = false;
760 maPresSettings.mbFullScreen = false;
761 maPresSettings.mbAnimationAllowed = true;
762 maPresSettings.mnPauseTimeout = 0;
763 maPresSettings.mbShowPauseLogo = false;
765 Reference< XDrawPagesSupplier > xDrawPages( mpDoc->getUnoModel(), UNO_QUERY_THROW );
766 Reference< XIndexAccess > xSlides( xDrawPages->getDrawPages(), UNO_QUERY_THROW );
767 mpSlideController = std::make_shared<AnimationSlideController>( xSlides, AnimationSlideController::PREVIEW );
769 sal_Int32 nSlideNumber = 0;
770 Reference< XPropertySet > xSet( mxPreviewDrawPage, UNO_QUERY_THROW );
771 xSet->getPropertyValue( "Number" ) >>= nSlideNumber;
772 mpSlideController->insertSlideNumber( nSlideNumber-1 );
773 mpSlideController->setPreviewNode( xAnimationNode );
775 mpShowWindow = VclPtr<ShowWindow>::Create( this, ((pParent == nullptr) && mpViewShell) ? mpParentWindow.get() : pParent );
776 if( mpViewShell )
778 mpViewShell->SetActiveWindow( mpShowWindow );
779 mpShowWindow->SetViewShell (mpViewShell);
780 mpViewShell->ShowUIControls (false);
783 if( mpView )
785 mpView->AddDeviceToPaintView( *mpShowWindow->GetOutDev(), nullptr );
786 mpView->SetAnimationPause( true );
789 // call resize handler
790 if( pParent )
792 maPresSize = pParent->GetSizePixel();
794 else if( mpViewShell )
796 ::tools::Rectangle aContentRect (mpViewShell->GetViewShellBase().getClientRectangle());
797 if (AllSettings::GetLayoutRTL())
799 aContentRect.SetLeft( aContentRect.Right() );
800 aContentRect.AdjustRight(aContentRect.Right() );
802 maPresSize = aContentRect.GetSize();
803 mpShowWindow->SetPosPixel( aContentRect.TopLeft() );
805 else
807 OSL_FAIL("sd::SlideshowImpl::startPreview(), I need either a parent window or a viewshell!");
809 resize( maPresSize );
811 sal_Int32 nPropertyCount = 1;
812 if( mxPreviewAnimationNode.is() )
813 nPropertyCount++;
815 Sequence< beans::PropertyValue > aProperties(nPropertyCount);
816 auto pProperties = aProperties.getArray();
817 pProperties[0].Name = "AutomaticAdvancement";
818 pProperties[0].Value <<= 1.0; // one second timeout
820 if( mxPreviewAnimationNode.is() )
822 pProperties[1].Name = "NoSlideTransitions";
823 pProperties[1].Value <<= true;
826 bRet = startShowImpl( aProperties );
828 if( mpShowWindow != nullptr && meAnimationMode == ANIMATIONMODE_PREVIEW )
829 mpShowWindow->SetPreviewMode();
832 catch( Exception& )
834 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::startPreview()" );
835 bRet = false;
838 return bRet;
841 bool SlideshowImpl::startShow( PresentationSettingsEx const * pPresSettings )
843 const rtl::Reference<SlideshowImpl> xKeepAlive(this);
845 DBG_ASSERT( !mxShow.is(), "sd::SlideshowImpl::startShow(), called twice!" );
846 if( mxShow.is() )
847 return true;
848 DBG_ASSERT( mpParentWindow!=nullptr, "sd::SlideshowImpl::startShow() called without parent window" );
849 if (mpParentWindow == nullptr)
850 return false;
852 // Autoplay (pps/ppsx)
853 if (mpViewShell->GetDoc()->IsStartWithPresentation()){
854 mpViewShell->GetDoc()->SetExitAfterPresenting(true);
857 bool bRet = false;
861 if( pPresSettings )
863 maPresSettings = *pPresSettings;
864 mbRehearseTimings = pPresSettings->mbRehearseTimings;
867 OUString aPresSlide( maPresSettings.maPresPage );
868 SdPage* pStartPage = mpViewShell->GetActualPage();
869 bool bStartWithActualSlide = pStartPage;
871 // times should be measured?
872 if( mbRehearseTimings )
874 maPresSettings.mbEndless = false;
875 maPresSettings.mbManual = true;
876 maPresSettings.mbMouseVisible = true;
877 maPresSettings.mbMouseAsPen = false;
878 maPresSettings.mnPauseTimeout = 0;
879 maPresSettings.mbShowPauseLogo = false;
880 maPresSettings.mbUseNavigation = false;
883 if( pStartPage )
885 if( pStartPage->GetPageKind() == PageKind::Notes )
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 );
894 if( bStartWithActualSlide )
896 if ( aPresSlide.isEmpty())
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();
904 if( meAnimationMode != ANIMATIONMODE_SHOW )
906 if( pStartPage->GetPageKind() == PageKind::Standard )
908 maPresSettings.mbAll = false;
913 // build page list
914 createSlideList( maPresSettings.mbAll, aPresSlide );
916 // remember Slide number from where the show was started
917 if( pStartPage )
918 mnRestoreSlide = ( pStartPage->GetPageNum() - 1 ) / 2;
920 if( mpSlideController->hasSlides() )
922 // hide child windows
923 hideChildWindows();
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));
934 // these Slots are forbidden in other views for this document
935 if( mpDocSh )
937 mpDocSh->SetSlotFilter( true, pAllowed );
938 mpDocSh->ApplySlotFilter();
941 Help::DisableContextHelp();
942 Help::DisableExtHelp();
944 if( maPresSettings.mbFullScreen )
946 #if HAVE_FEATURE_SCRIPTING
947 // disable basic ide error handling
948 maStarBASICGlobalErrorHdl = StarBASIC::GetGlobalErrorHdl();
949 StarBASIC::SetGlobalErrorHdl( Link<StarBASIC*,bool>() );
950 #endif
953 // call resize handler
954 maPresSize = mpParentWindow->GetSizePixel();
955 if (!maPresSettings.mbFullScreen)
957 const ::tools::Rectangle& aClientRect = mpViewShell->GetViewShellBase().getClientRectangle();
958 maPresSize = aClientRect.GetSize();
959 mpShowWindow->SetPosPixel( aClientRect.TopLeft() );
960 resize( maPresSize );
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
970 if( mpView )
972 mpView->AddDeviceToPaintView( *mpShowWindow->GetOutDev(), nullptr );
973 mpView->SetAnimationPause( true );
976 SfxBindings* pBindings = getBindings();
977 if( pBindings )
979 pBindings->Invalidate( SID_PRESENTATION );
980 pBindings->Invalidate( SID_REHEARSE_TIMINGS );
983 // Defer the sd::ShowWindow's GrabFocus to SlideShow::activate. so that the accessible event can be fired correctly.
984 //mpShowWindow->GrabFocus();
986 std::vector<beans::PropertyValue> aProperties;
987 aProperties.reserve( 4 );
989 aProperties.emplace_back( "AdvanceOnClick" ,
990 -1, Any( !maPresSettings.mbLockedPages ),
991 beans::PropertyState_DIRECT_VALUE );
993 aProperties.emplace_back( "ImageAnimationsAllowed" ,
994 -1, Any( maPresSettings.mbAnimationAllowed ),
995 beans::PropertyState_DIRECT_VALUE );
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 );
1003 aProperties.emplace_back( "ForceManualAdvance" ,
1004 -1, Any( maPresSettings.mbManual ),
1005 beans::PropertyState_DIRECT_VALUE );
1007 if( mbUsePen )
1009 aProperties.emplace_back( "UserPaintColor" ,
1010 // User paint color is black by default.
1011 -1, Any( mnUserPaintColor ),
1012 beans::PropertyState_DIRECT_VALUE );
1014 aProperties.emplace_back( "UserPaintStrokeWidth" ,
1015 // User paint color is black by default.
1016 -1, Any( mdUserPaintStrokeWidth ),
1017 beans::PropertyState_DIRECT_VALUE );
1020 if (mbRehearseTimings) {
1021 aProperties.emplace_back( "RehearseTimings" ,
1022 -1, Any(true), beans::PropertyState_DIRECT_VALUE );
1025 bRet = startShowImpl( Sequence<beans::PropertyValue>(
1026 aProperties.data(), aProperties.size() ) );
1030 setActiveXToolbarsVisible( false );
1032 catch (const Exception&)
1034 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::startShow()" );
1035 bRet = false;
1038 return bRet;
1041 bool SlideshowImpl::startShowImpl( const Sequence< beans::PropertyValue >& aProperties )
1045 mxShow.set( createSlideShow(), UNO_SET_THROW );
1047 mxView = new SlideShowView(
1048 *mpShowWindow,
1049 mpDoc,
1050 meAnimationMode,
1051 this,
1052 maPresSettings.mbFullScreen);
1054 // try add wait symbol to properties:
1055 const Reference<rendering::XSpriteCanvas> xSpriteCanvas(
1056 mxView->getCanvas() );
1057 if (xSpriteCanvas.is())
1059 BitmapEx waitSymbolBitmap(BMP_WAIT_ICON);
1060 const Reference<rendering::XBitmap> xBitmap(
1061 vcl::unotools::xBitmapFromBitmapEx( waitSymbolBitmap ) );
1062 if (xBitmap.is())
1064 mxShow->setProperty(
1065 beans::PropertyValue( "WaitSymbolBitmap" ,
1067 Any( xBitmap ),
1068 beans::PropertyState_DIRECT_VALUE ) );
1071 BitmapEx pointerSymbolBitmap(BMP_POINTER_ICON);
1072 const Reference<rendering::XBitmap> xPointerBitmap(
1073 vcl::unotools::xBitmapFromBitmapEx( pointerSymbolBitmap ) );
1074 if (xPointerBitmap.is())
1076 mxShow->setProperty(
1077 beans::PropertyValue( "PointerSymbolBitmap" ,
1079 Any( xPointerBitmap ),
1080 beans::PropertyState_DIRECT_VALUE ) );
1083 if (maPresSettings.mbUseNavigation)
1085 BitmapEx prevSlideBm(BMP_PREV_SLIDE);
1086 const Reference<rendering::XBitmap> xPrevSBitmap(
1087 vcl::unotools::xBitmapFromBitmapEx(prevSlideBm));
1088 if (xPrevSBitmap.is())
1090 mxShow->setProperty(beans::PropertyValue("NavigationSlidePrev", -1,
1091 Any(xPrevSBitmap),
1092 beans::PropertyState_DIRECT_VALUE));
1094 BitmapEx menuSlideBm(BMP_MENU_SLIDE);
1095 const Reference<rendering::XBitmap> xMenuSBitmap(
1096 vcl::unotools::xBitmapFromBitmapEx(menuSlideBm));
1097 if (xMenuSBitmap.is())
1099 mxShow->setProperty(beans::PropertyValue("NavigationSlideMenu", -1,
1100 Any(xMenuSBitmap),
1101 beans::PropertyState_DIRECT_VALUE));
1103 BitmapEx nextSlideBm(BMP_NEXT_SLIDE);
1104 const Reference<rendering::XBitmap> xNextSBitmap(
1105 vcl::unotools::xBitmapFromBitmapEx(nextSlideBm));
1106 if (xNextSBitmap.is())
1108 mxShow->setProperty(beans::PropertyValue("NavigationSlideNext", -1,
1109 Any(xNextSBitmap),
1110 beans::PropertyState_DIRECT_VALUE));
1115 for( const auto& rProp : aProperties )
1116 mxShow->setProperty( rProp );
1118 mxShow->addView( mxView );
1120 mxListenerProxy.set( new SlideShowListenerProxy( this, mxShow ) );
1121 mxListenerProxy->addAsSlideShowListener();
1123 NotifyDocumentEvent(
1124 *mpDoc,
1125 "OnStartPresentation");
1126 displaySlideIndex( mpSlideController->getStartSlideIndex() );
1128 return true;
1130 catch( Exception& )
1132 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::startShowImpl()" );
1133 return false;
1137 /** called only by the slideshow view when the first paint event occurs.
1138 This actually starts the slideshow. */
1139 void SlideshowImpl::onFirstPaint()
1141 if( mpShowWindow )
1144 mpShowWindow->SetBackground( Wallpaper( COL_BLACK ) );
1145 mpShowWindow->Erase();
1146 mpShowWindow->SetBackground();
1150 SolarMutexGuard aSolarGuard;
1151 maUpdateTimer.SetTimeout( sal_uLong(100) );
1152 maUpdateTimer.Start();
1155 void SlideshowImpl::paint()
1157 if( mxView.is() ) try
1159 awt::PaintEvent aEvt;
1160 // aEvt.UpdateRect = TODO
1161 mxView->paint( aEvt );
1163 catch( Exception& )
1165 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::paint()" );
1169 void SAL_CALL SlideshowImpl::addSlideShowListener( const Reference< XSlideShowListener >& xListener )
1171 if( mxListenerProxy.is() )
1172 mxListenerProxy->addSlideShowListener( xListener );
1175 void SAL_CALL SlideshowImpl::removeSlideShowListener( const Reference< XSlideShowListener >& xListener )
1177 if( mxListenerProxy.is() )
1178 mxListenerProxy->removeSlideShowListener( xListener );
1181 void SlideshowImpl::slideEnded(const bool bReverse)
1183 if (bReverse)
1184 gotoPreviousSlide(true);
1185 else
1186 gotoNextSlide();
1189 bool SlideshowImpl::swipe(const CommandGestureSwipeData &rSwipeData)
1191 if (mbUsePen || mnContextMenuEvent)
1192 return false;
1193 double nVelocityX = rSwipeData.getVelocityX();
1194 // tdf#108475 make it swipe only if some reasonable movement was involved
1195 if (fabs(nVelocityX) < 50)
1196 return false;
1197 if (nVelocityX > 0)
1199 gotoPreviousSlide();
1201 else
1203 gotoNextEffect();
1205 //a swipe is followed by a mouse up, tell the view to ignore that mouse up as we've reacted
1206 //to the swipe instead
1207 mxView->ignoreNextMouseReleased();
1208 return true;
1211 bool SlideshowImpl::longpress(const CommandGestureLongPressData &rLongPressData)
1213 if (mnContextMenuEvent)
1214 return false;
1216 maPopupMousePos = Point(rLongPressData.getX(), rLongPressData.getY());
1217 mnContextMenuEvent = Application::PostUserEvent( LINK( this, SlideshowImpl, ContextMenuHdl ) );
1219 return true;
1222 void SlideshowImpl::removeShapeEvents()
1224 if( !(mxShow.is() && mxListenerProxy.is()) )
1225 return;
1229 for( const auto& rEntry : maShapeEventMap )
1231 mxListenerProxy->removeShapeEventListener( rEntry.first );
1232 mxShow->setShapeCursor( rEntry.first, awt::SystemPointer::ARROW );
1235 maShapeEventMap.clear();
1237 catch( Exception& )
1239 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::removeShapeEvents()" );
1243 void SlideshowImpl::registerShapeEvents(sal_Int32 nSlideNumber)
1245 if( nSlideNumber < 0 )
1246 return;
1250 Reference< XDrawPagesSupplier > xDrawPages( mxModel, UNO_QUERY_THROW );
1251 Reference< XIndexAccess > xPages( xDrawPages->getDrawPages(), UNO_QUERY_THROW );
1253 Reference< XShapes > xDrawPage;
1254 xPages->getByIndex(nSlideNumber) >>= xDrawPage;
1256 if( xDrawPage.is() )
1258 Reference< XMasterPageTarget > xMasterPageTarget( xDrawPage, UNO_QUERY );
1259 if( xMasterPageTarget.is() )
1261 Reference< XShapes > xMasterPage = xMasterPageTarget->getMasterPage();
1262 if( xMasterPage.is() )
1263 registerShapeEvents( xMasterPage );
1265 registerShapeEvents( xDrawPage );
1268 catch( Exception& )
1270 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::registerShapeEvents()" );
1274 void SlideshowImpl::registerShapeEvents( Reference< XShapes > const & xShapes )
1278 const sal_Int32 nShapeCount = xShapes->getCount();
1279 sal_Int32 nShape;
1280 for( nShape = 0; nShape < nShapeCount; nShape++ )
1282 Reference< XShape > xShape;
1283 xShapes->getByIndex( nShape ) >>= xShape;
1285 if( xShape.is() && xShape->getShapeType() == "com.sun.star.drawing.GroupShape" )
1287 Reference< XShapes > xSubShapes( xShape, UNO_QUERY );
1288 if( xSubShapes.is() )
1289 registerShapeEvents( xSubShapes );
1292 Reference< XPropertySet > xSet( xShape, UNO_QUERY );
1293 if( !xSet.is() )
1294 continue;
1296 Reference< XPropertySetInfo > xSetInfo( xSet->getPropertySetInfo() );
1297 if( !xSetInfo.is() || !xSetInfo->hasPropertyByName( gsOnClick ) )
1298 continue;
1300 WrappedShapeEventImplPtr pEvent = std::make_shared<WrappedShapeEventImpl>();
1301 xSet->getPropertyValue( gsOnClick ) >>= pEvent->meClickAction;
1303 switch( pEvent->meClickAction )
1305 case ClickAction_PREVPAGE:
1306 case ClickAction_NEXTPAGE:
1307 case ClickAction_FIRSTPAGE:
1308 case ClickAction_LASTPAGE:
1309 case ClickAction_STOPPRESENTATION:
1310 break;
1311 case ClickAction_BOOKMARK:
1312 if( xSetInfo->hasPropertyByName( gsBookmark ) )
1313 xSet->getPropertyValue( gsBookmark ) >>= pEvent->maStrBookmark;
1314 if( getSlideNumberForBookmark( pEvent->maStrBookmark ) == -1 )
1315 continue;
1316 break;
1317 case ClickAction_DOCUMENT:
1318 case ClickAction_SOUND:
1319 case ClickAction_PROGRAM:
1320 case ClickAction_MACRO:
1321 if( xSetInfo->hasPropertyByName( gsBookmark ) )
1322 xSet->getPropertyValue( gsBookmark ) >>= pEvent->maStrBookmark;
1323 break;
1324 case ClickAction_VERB:
1325 if( xSetInfo->hasPropertyByName( gsVerb ) )
1326 xSet->getPropertyValue( gsVerb ) >>= pEvent->mnVerb;
1327 break;
1328 default:
1329 continue; // skip all others
1332 maShapeEventMap[ xShape ] = pEvent;
1334 if( mxListenerProxy.is() )
1335 mxListenerProxy->addShapeEventListener( xShape );
1336 mxShow->setShapeCursor( xShape, awt::SystemPointer::REFHAND );
1339 catch( Exception& )
1341 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::registerShapeEvents()" );
1345 void SlideshowImpl::displayCurrentSlide (const bool bSkipAllMainSequenceEffects)
1347 stopSound();
1348 removeShapeEvents();
1350 if( mpSlideController && mxShow.is() )
1352 Reference< XDrawPagesSupplier > xDrawPages( mpDoc->getUnoModel(),
1353 UNO_QUERY_THROW );
1354 mpSlideController->displayCurrentSlide( mxShow, xDrawPages, bSkipAllMainSequenceEffects );
1355 registerShapeEvents(mpSlideController->getCurrentSlideNumber());
1356 update();
1359 // send out page change event and notify to update all acc info for current page
1360 if (mpViewShell)
1362 sal_Int32 currentPageIndex = getCurrentSlideIndex();
1363 mpViewShell->fireSwitchCurrentPage(currentPageIndex);
1364 mpViewShell->NotifyAccUpdate();
1368 void SlideshowImpl::endPresentation()
1370 if( maPresSettings.mbMouseAsPen)
1372 Reference< XMultiServiceFactory > xDocFactory(mpDoc->getUnoModel(), UNO_QUERY );
1373 if( xDocFactory.is() )
1374 mxShow->registerUserPaintPolygons(xDocFactory);
1377 if( !mnEndShowEvent )
1378 mnEndShowEvent = Application::PostUserEvent( LINK(this, SlideshowImpl, endPresentationHdl) );
1381 IMPL_LINK_NOARG(SlideshowImpl, endPresentationHdl, void*, void)
1383 mnEndShowEvent = nullptr;
1385 stopSound();
1387 if( mxPresentation.is() )
1388 mxPresentation->end();
1391 void SAL_CALL SlideshowImpl::pause()
1393 SolarMutexGuard aSolarGuard;
1395 if( mbIsPaused )
1396 return;
1400 mbIsPaused = true;
1401 if( mxShow.is() )
1403 mxShow->pause(true);
1405 if( mxListenerProxy.is() )
1406 mxListenerProxy->paused();
1409 catch( Exception& )
1411 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::pause()" );
1415 void SAL_CALL SlideshowImpl::resume()
1417 SolarMutexGuard aSolarGuard;
1419 if( mbIsPaused ) try
1421 if( mpShowWindow->GetShowWindowMode() == SHOWWINDOWMODE_BLANK || mpShowWindow->GetShowWindowMode() == SHOWWINDOWMODE_END )
1423 mpShowWindow->RestartShow();
1425 else
1427 mbIsPaused = false;
1428 if( mxShow.is() )
1430 mxShow->pause(false);
1431 update();
1433 if( mxListenerProxy.is() )
1434 mxListenerProxy->resumed();
1438 catch( Exception& )
1440 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::resume()" );
1442 #ifdef ENABLE_SDREMOTE
1443 RemoteServer::presentationStarted( this );
1444 #endif
1447 sal_Bool SAL_CALL SlideshowImpl::isPaused()
1449 SolarMutexGuard aSolarGuard;
1450 return mbIsPaused;
1453 void SAL_CALL SlideshowImpl::blankScreen( sal_Int32 nColor )
1455 SolarMutexGuard aSolarGuard;
1457 if( mpShowWindow && mpSlideController )
1459 if( mpShowWindow->SetBlankMode( mpSlideController->getCurrentSlideIndex(), Color(ColorTransparency, nColor) ) )
1461 pause();
1466 // XShapeEventListener
1468 void SlideshowImpl::click( const Reference< XShape >& xShape )
1470 SolarMutexGuard aSolarGuard;
1472 WrappedShapeEventImplPtr pEvent = maShapeEventMap[xShape];
1473 if( !pEvent )
1474 return;
1476 switch( pEvent->meClickAction )
1478 case ClickAction_PREVPAGE: gotoPreviousSlide(); break;
1479 case ClickAction_NEXTPAGE: gotoNextSlide(); break;
1480 case ClickAction_FIRSTPAGE: gotoFirstSlide(); break;
1481 case ClickAction_LASTPAGE: gotoLastSlide(); break;
1482 case ClickAction_STOPPRESENTATION: endPresentation(); break;
1483 case ClickAction_BOOKMARK:
1485 gotoBookmark( pEvent->maStrBookmark );
1487 break;
1488 case ClickAction_SOUND:
1490 #if HAVE_FEATURE_AVMEDIA
1493 mxPlayer.set(avmedia::MediaWindow::createPlayer(pEvent->maStrBookmark, ""/*TODO?*/), uno::UNO_SET_THROW );
1494 mxPlayer->start();
1496 catch( uno::Exception& )
1498 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::click()" );
1500 #endif
1502 break;
1504 case ClickAction_DOCUMENT:
1506 OUString aBookmark( pEvent->maStrBookmark );
1508 sal_Int32 nPos = aBookmark.indexOf( '#' );
1509 if( nPos >= 0 )
1511 OUString aURL( aBookmark.copy( 0, nPos+1 ) );
1512 OUString aName( aBookmark.copy( nPos+1 ) );
1513 aURL += getUiNameFromPageApiNameImpl( aName );
1514 aBookmark = aURL;
1517 mpDocSh->OpenBookmark( aBookmark );
1519 break;
1521 case ClickAction_PROGRAM:
1523 INetURLObject aURL(
1524 ::URIHelper::SmartRel2Abs(
1525 INetURLObject(mpDocSh->GetMedium()->GetBaseURL()),
1526 pEvent->maStrBookmark, ::URIHelper::GetMaybeFileHdl(), true,
1527 false, INetURLObject::EncodeMechanism::WasEncoded,
1528 INetURLObject::DecodeMechanism::Unambiguous ) );
1530 if( INetProtocol::File == aURL.GetProtocol() )
1532 SfxStringItem aUrl( SID_FILE_NAME, aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
1533 SfxBoolItem aBrowsing( SID_BROWSE, true );
1535 if (SfxViewFrame* pViewFrm = SfxViewFrame::Current())
1537 SfxUnoFrameItem aDocFrame(SID_FILLFRAME, pViewFrm->GetFrame().GetFrameInterface());
1538 pViewFrm->GetDispatcher()->ExecuteList( SID_OPENDOC,
1539 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD,
1540 { &aUrl, &aBrowsing }, { &aDocFrame } );
1544 break;
1546 #if HAVE_FEATURE_SCRIPTING
1547 case presentation::ClickAction_MACRO:
1549 const OUString aMacro( pEvent->maStrBookmark );
1551 if ( SfxApplication::IsXScriptURL( aMacro ) )
1553 Any aRet;
1554 Sequence< sal_Int16 > aOutArgsIndex;
1555 Sequence< Any > aOutArgs;
1556 Sequence< Any >* pInArgs = new Sequence< Any >(0);
1557 mpDocSh->CallXScript( aMacro, *pInArgs, aRet, aOutArgsIndex, aOutArgs);
1559 else
1561 // aMacro has the following syntax:
1562 // "Macroname.Modulname.Libname.Documentname" or
1563 // "Macroname.Modulname.Libname.Applicationname"
1564 sal_Int32 nIdx{ 0 };
1565 const std::u16string_view aMacroName = o3tl::getToken(aMacro, 0, '.', nIdx);
1566 const std::u16string_view aModulName = o3tl::getToken(aMacro, 0, '.', nIdx);
1568 // todo: is the limitation still given that only
1569 // Modulname+Macroname can be used here?
1570 OUString aExecMacro = OUString::Concat(aModulName) + "." + aMacroName;
1571 mpDocSh->GetBasic()->Call(aExecMacro);
1574 break;
1575 #endif
1577 case ClickAction_VERB:
1579 // todo, better do it async?
1580 SdrObject* pObj = SdrObject::getSdrObjectFromXShape(xShape);
1581 SdrOle2Obj* pOleObject = dynamic_cast< SdrOle2Obj* >(pObj);
1582 if (pOleObject && mpViewShell )
1583 mpViewShell->ActivateObject(pOleObject, pEvent->mnVerb);
1585 break;
1586 default:
1587 break;
1591 sal_Int32 SlideshowImpl::getSlideNumberForBookmark( const OUString& rStrBookmark )
1593 bool bIsMasterPage;
1594 OUString aBookmark = getUiNameFromPageApiNameImpl( rStrBookmark );
1595 sal_uInt16 nPgNum = mpDoc->GetPageByName( aBookmark, bIsMasterPage );
1597 if( nPgNum == SDRPAGE_NOTFOUND )
1599 // Is the bookmark an object?
1600 SdrObject* pObj = mpDoc->GetObj( aBookmark );
1602 if( pObj )
1604 nPgNum = pObj->getSdrPageFromSdrObject()->GetPageNum();
1605 bIsMasterPage = pObj->getSdrPageFromSdrObject()->IsMasterPage();
1609 if( (nPgNum == SDRPAGE_NOTFOUND) || bIsMasterPage || static_cast<SdPage*>(mpDoc->GetPage(nPgNum))->GetPageKind() != PageKind::Standard )
1610 return -1;
1612 return ( nPgNum - 1) >> 1;
1615 void SlideshowImpl::contextMenuShow(const css::awt::Point& point)
1617 maPopupMousePos = { point.X, point.Y };
1618 mnContextMenuEvent = Application::PostUserEvent(LINK(this, SlideshowImpl, ContextMenuHdl));
1621 void SlideshowImpl::hyperLinkClicked( OUString const& aHyperLink )
1623 OUString aBookmark( aHyperLink );
1625 sal_Int32 nPos = aBookmark.indexOf( '#' );
1626 if( nPos >= 0 )
1628 OUString aURL( aBookmark.copy( 0, nPos+1 ) );
1629 OUString aName( aBookmark.copy( nPos+1 ) );
1630 aURL += getUiNameFromPageApiNameImpl( aName );
1631 aBookmark = aURL;
1634 mpDocSh->OpenBookmark( aBookmark );
1637 void SlideshowImpl::displaySlideNumber( sal_Int32 nSlideNumber )
1639 if( mpSlideController )
1641 if( mpSlideController->jumpToSlideNumber( nSlideNumber ) )
1643 displayCurrentSlide();
1648 /** nSlideIndex == -1 displays current slide again */
1649 void SlideshowImpl::displaySlideIndex( sal_Int32 nSlideIndex )
1651 if( mpSlideController )
1653 if( (nSlideIndex == -1) || mpSlideController->jumpToSlideIndex( nSlideIndex ) )
1655 displayCurrentSlide();
1660 void SlideshowImpl::jumpToBookmark( const OUString& sBookmark )
1662 sal_Int32 nSlideNumber = getSlideNumberForBookmark( sBookmark );
1663 if( nSlideNumber != -1 )
1664 displaySlideNumber( nSlideNumber );
1667 sal_Int32 SlideshowImpl::getCurrentSlideNumber() const
1669 return mpSlideController ? mpSlideController->getCurrentSlideNumber() : -1;
1672 sal_Bool SAL_CALL SlideshowImpl::isEndless()
1674 SolarMutexGuard aSolarGuard;
1675 return maPresSettings.mbEndless;
1678 void SlideshowImpl::update()
1680 startUpdateTimer();
1683 void SlideshowImpl::startUpdateTimer()
1685 SolarMutexGuard aSolarGuard;
1686 maUpdateTimer.SetTimeout( 0 );
1687 maUpdateTimer.Start();
1690 /** this timer is called 20ms after a new slide was displayed.
1691 This is used to unfreeze user input that was disabled after
1692 slide change to skip input that was buffered during slide
1693 transition preparation */
1694 IMPL_LINK_NOARG(SlideshowImpl, ReadyForNextInputHdl, Timer *, void)
1696 mbInputFreeze = false;
1699 /** if I catch someone someday who calls this method by hand
1700 and not by using the timer, I will personally punish this
1701 person seriously, even if this person is me.
1703 IMPL_LINK_NOARG(SlideshowImpl, updateHdl, Timer *, void)
1705 updateSlideShow();
1708 void SlideshowImpl::updateSlideShow()
1710 // prevent me from deletion when recursing (App::EnableYieldMode does)
1711 const rtl::Reference<SlideshowImpl> xKeepAlive(this);
1713 Reference< XSlideShow > xShow( mxShow );
1714 if ( ! xShow.is())
1715 return;
1719 double fUpdate = 0.0;
1720 if( !xShow->update(fUpdate) )
1721 fUpdate = -1.0;
1723 if (mxShow.is() && (fUpdate >= 0.0))
1725 if (::basegfx::fTools::equalZero(fUpdate))
1727 // Make sure idle tasks don't starve when we don't have to wait.
1728 // Don't process any events generated after invoking the function.
1729 Application::Reschedule(/*bHandleAllCurrentEvents=*/true);
1731 else
1733 // Avoid busy loop when the previous call to update()
1734 // returns a small positive number but not 0 (which is
1735 // handled above). Also, make sure that calls to update()
1736 // have a minimum frequency.
1737 // => Allow up to 60 frames per second. Call at least once
1738 // every 4 seconds.
1739 const static sal_Int32 nMaximumFrameCount (60);
1740 const static double nMinimumTimeout (1.0 / nMaximumFrameCount);
1741 const static double nMaximumTimeout (4.0);
1742 fUpdate = std::clamp(fUpdate, nMinimumTimeout, nMaximumTimeout);
1744 // Make sure that the maximum frame count has not been set
1745 // too high (only then conversion to milliseconds and long
1746 // integer may lead to zero value.)
1747 OSL_ASSERT(static_cast<sal_uLong>(fUpdate * 1000.0) > 0);
1750 // Use our high resolution timers for the asynchronous callback.
1751 maUpdateTimer.SetTimeout(static_cast<sal_uLong>(fUpdate * 1000.0));
1752 maUpdateTimer.Start();
1755 catch( Exception& )
1757 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::updateSlideShow()" );
1761 bool SlideshowImpl::keyInput(const KeyEvent& rKEvt)
1763 if( !mxShow.is() || mbInputFreeze )
1764 return false;
1766 bool bRet = true;
1770 const int nKeyCode = rKEvt.GetKeyCode().GetCode();
1771 switch( nKeyCode )
1773 case awt::Key::CONTEXTMENU:
1774 if( !mnContextMenuEvent )
1776 if( mpShowWindow )
1777 maPopupMousePos = mpShowWindow->GetPointerState().maPos;
1778 mnContextMenuEvent = Application::PostUserEvent( LINK( this, SlideshowImpl, ContextMenuHdl ) );
1780 break;
1782 // cancel show
1783 case KEY_ESCAPE:
1784 case KEY_SUBTRACT:
1785 // in case the user cancels the presentation, switch to current slide
1786 // in edit mode
1787 if( mpSlideController && (ANIMATIONMODE_SHOW == meAnimationMode) )
1789 if( mpSlideController->getCurrentSlideNumber() != -1 )
1790 mnRestoreSlide = mpSlideController->getCurrentSlideNumber();
1792 endPresentation();
1793 break;
1795 // advance show
1796 case KEY_PAGEDOWN:
1797 if(rKEvt.GetKeyCode().IsMod2())
1799 gotoNextSlide();
1800 break;
1802 [[fallthrough]];
1803 case KEY_SPACE:
1804 case KEY_RIGHT:
1805 case KEY_DOWN:
1806 gotoNextEffect();
1807 break;
1809 case KEY_RETURN:
1811 if( !maCharBuffer.isEmpty() )
1813 if( mpSlideController )
1815 if( mpSlideController->jumpToSlideNumber( maCharBuffer.toInt32() - 1 ) )
1816 displayCurrentSlide();
1818 maCharBuffer.clear();
1820 else
1822 gotoNextEffect();
1825 break;
1827 // numeric: add to buffer
1828 case KEY_0:
1829 case KEY_1:
1830 case KEY_2:
1831 case KEY_3:
1832 case KEY_4:
1833 case KEY_5:
1834 case KEY_6:
1835 case KEY_7:
1836 case KEY_8:
1837 case KEY_9:
1838 maCharBuffer += OUStringChar( rKEvt.GetCharCode() );
1839 break;
1841 case KEY_PAGEUP:
1842 if(rKEvt.GetKeyCode().IsMod2())
1844 gotoPreviousSlide();
1845 break;
1847 [[fallthrough]];
1848 case KEY_LEFT:
1849 case KEY_UP:
1850 case KEY_BACKSPACE:
1851 gotoPreviousEffect();
1852 break;
1854 case KEY_P:
1855 setUsePen( !mbUsePen );
1856 break;
1858 // tdf#149351 Ctrl+A disables pointer as pen mode
1859 case KEY_A:
1860 if(rKEvt.GetKeyCode().IsMod1())
1862 setUsePen( false );
1863 break;
1865 break;
1867 case KEY_E:
1868 setEraseAllInk( true );
1869 updateSlideShow();
1870 break;
1872 case KEY_HOME:
1873 gotoFirstSlide();
1874 break;
1876 case KEY_END:
1877 gotoLastSlide();
1878 break;
1880 case KEY_B:
1881 case KEY_W:
1882 case KEY_POINT:
1883 case KEY_COMMA:
1885 blankScreen( ((nKeyCode == KEY_W ) || (nKeyCode == KEY_COMMA)) ? 0x00ffffff : 0x00000000 );
1887 break;
1889 default:
1890 bRet = false;
1891 break;
1894 catch( Exception& )
1896 bRet = false;
1897 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::keyInput()" );
1900 return bRet;
1903 IMPL_LINK( SlideshowImpl, EventListenerHdl, VclSimpleEvent&, rSimpleEvent, void )
1905 if( !mxShow.is() || mbInputFreeze )
1906 return;
1908 if( !((rSimpleEvent.GetId() == VclEventId::WindowCommand) && static_cast<VclWindowEvent*>(&rSimpleEvent)->GetData()) )
1909 return;
1911 const CommandEvent& rEvent = *static_cast<const CommandEvent*>(static_cast<VclWindowEvent*>(&rSimpleEvent)->GetData());
1913 if( rEvent.GetCommand() != CommandEventId::Media )
1914 return;
1916 CommandMediaData* pMediaData = rEvent.GetMediaData();
1917 pMediaData->SetPassThroughToOS(false);
1918 switch (pMediaData->GetMediaId())
1920 #if defined( MACOSX )
1921 case MediaCommand::Menu:
1922 if( !mnContextMenuEvent )
1924 if( mpShowWindow )
1925 maPopupMousePos = mpShowWindow->GetPointerState().maPos;
1926 mnContextMenuEvent = Application::PostUserEvent( LINK( this, SlideshowImpl, ContextMenuHdl ) );
1928 break;
1929 case MediaCommand::VolumeDown:
1930 gotoPreviousSlide();
1931 break;
1932 case MediaCommand::VolumeUp:
1933 gotoNextEffect();
1934 break;
1935 #endif
1936 case MediaCommand::NextTrack:
1937 gotoNextEffect();
1938 break;
1939 case MediaCommand::Pause:
1940 if( !mbIsPaused )
1941 blankScreen(0);
1942 break;
1943 case MediaCommand::Play:
1944 if( mbIsPaused )
1945 resume();
1946 break;
1948 case MediaCommand::PlayPause:
1949 if( mbIsPaused )
1950 resume();
1951 else
1952 blankScreen(0);
1953 break;
1954 case MediaCommand::PreviousTrack:
1955 gotoPreviousSlide();
1956 break;
1957 case MediaCommand::NextTrackHold:
1958 gotoLastSlide();
1959 break;
1961 case MediaCommand::Rewind:
1962 gotoFirstSlide();
1963 break;
1964 case MediaCommand::Stop:
1965 // in case the user cancels the presentation, switch to current slide
1966 // in edit mode
1967 if( mpSlideController && (ANIMATIONMODE_SHOW == meAnimationMode) )
1969 if( mpSlideController->getCurrentSlideNumber() != -1 )
1970 mnRestoreSlide = mpSlideController->getCurrentSlideNumber();
1972 endPresentation();
1973 break;
1974 default:
1975 pMediaData->SetPassThroughToOS(true);
1976 break;
1980 void SlideshowImpl::mouseButtonUp(const MouseEvent& rMEvt)
1982 if( rMEvt.IsRight() && !mnContextMenuEvent )
1984 maPopupMousePos = rMEvt.GetPosPixel();
1985 mnContextMenuEvent = Application::PostUserEvent( LINK( this, SlideshowImpl, ContextMenuHdl ) );
1989 IMPL_LINK_NOARG(SlideshowImpl, ContextMenuHdl, void*, void)
1991 mnContextMenuEvent = nullptr;
1993 if (mpSlideController == nullptr)
1994 return;
1996 mbWasPaused = mbIsPaused;
1997 if( !mbWasPaused )
1998 pause();
2000 std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(nullptr, "modules/simpress/ui/slidecontextmenu.ui"));
2001 std::unique_ptr<weld::Menu> xMenu(xBuilder->weld_menu("menu"));
2002 OUString sNextImage(BMP_MENU_NEXT), sPrevImage(BMP_MENU_PREV);
2003 xMenu->insert(0, "next", SdResId(RID_SVXSTR_MENU_NEXT), &sNextImage, nullptr, nullptr, TRISTATE_INDET);
2004 xMenu->insert(1, "prev", SdResId(RID_SVXSTR_MENU_PREV), &sPrevImage, nullptr, nullptr, TRISTATE_INDET);
2006 // Adding button to display if in Pen mode
2007 xMenu->set_active("pen", mbUsePen);
2009 const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode();
2010 xMenu->set_visible("next", mpSlideController->getNextSlideIndex() != -1);
2011 xMenu->set_visible("prev", (mpSlideController->getPreviousSlideIndex() != -1 ) || (eMode == SHOWWINDOWMODE_END) || (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK));
2012 xMenu->set_visible("edit", mpViewShell->GetDoc()->IsStartWithPresentation());
2014 std::unique_ptr<weld::Menu> xPageMenu(xBuilder->weld_menu("gotomenu"));
2015 OUString sFirstImage(BMP_MENU_FIRST), sLastImage(BMP_MENU_LAST);
2016 xPageMenu->insert(0, "first", SdResId(RID_SVXSTR_MENU_FIRST), &sFirstImage, nullptr, nullptr, TRISTATE_INDET);
2017 xPageMenu->insert(1, "last", SdResId(RID_SVXSTR_MENU_LAST), &sLastImage, nullptr, nullptr, TRISTATE_INDET);
2019 // populate slide goto list
2020 const sal_Int32 nPageNumberCount = mpSlideController->getSlideNumberCount();
2021 if( nPageNumberCount <= 1 )
2023 xMenu->set_visible("goto", false);
2025 else
2027 sal_Int32 nCurrentSlideNumber = mpSlideController->getCurrentSlideNumber();
2028 if( (eMode == SHOWWINDOWMODE_END) || (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) )
2029 nCurrentSlideNumber = -1;
2031 xPageMenu->set_visible("first", mpSlideController->getSlideNumber(0) != nCurrentSlideNumber);
2032 xPageMenu->set_visible("last", mpSlideController->getSlideNumber(mpSlideController->getSlideIndexCount() - 1) != nCurrentSlideNumber);
2034 sal_Int32 nPageNumber;
2036 for( nPageNumber = 0; nPageNumber < nPageNumberCount; nPageNumber++ )
2038 if( mpSlideController->isVisibleSlideNumber( nPageNumber ) )
2040 SdPage* pPage = mpDoc->GetSdPage(static_cast<sal_uInt16>(nPageNumber), PageKind::Standard);
2041 if (pPage)
2043 OUString sId(OUString::number(CM_SLIDES + nPageNumber));
2044 xPageMenu->append_check(sId, pPage->GetName());
2045 if (nPageNumber == nCurrentSlideNumber)
2046 xPageMenu->set_active(sId, true);
2052 std::unique_ptr<weld::Menu> xBlankMenu(xBuilder->weld_menu("screenmenu"));
2054 if (mpShowWindow->GetShowWindowMode() == SHOWWINDOWMODE_BLANK)
2056 xBlankMenu->set_active((mpShowWindow->GetBlankColor() == COL_WHITE) ? "white" : "black", true);
2059 std::unique_ptr<weld::Menu> xWidthMenu(xBuilder->weld_menu("widthmenu"));
2061 // populate color width list
2062 sal_Int32 nIterator;
2063 double nWidth;
2065 nWidth = 4.0;
2066 for( nIterator = 1; nIterator < 6; nIterator++)
2068 switch(nIterator)
2070 case 1:
2071 nWidth = 4.0;
2072 break;
2073 case 2:
2074 nWidth = 100.0;
2075 break;
2076 case 3:
2077 nWidth = 150.0;
2078 break;
2079 case 4:
2080 nWidth = 200.0;
2081 break;
2082 case 5:
2083 nWidth = 400.0;
2084 break;
2085 default:
2086 break;
2089 if (nWidth == mdUserPaintStrokeWidth)
2090 xWidthMenu->set_active(OUString::number(nWidth), true);
2093 ::tools::Rectangle aRect(maPopupMousePos, Size(1,1));
2094 weld::Window* pParent = weld::GetPopupParent(*mpShowWindow, aRect);
2095 ContextMenuSelectHdl(xMenu->popup_at_rect(pParent, aRect));
2097 if( mxView.is() )
2098 mxView->ignoreNextMouseReleased();
2100 if( !mbWasPaused )
2101 resume();
2104 void SlideshowImpl::ContextMenuSelectHdl(std::u16string_view rMenuId)
2106 if (rMenuId == u"prev")
2108 gotoPreviousSlide();
2109 mbWasPaused = false;
2111 else if(rMenuId == u"next")
2113 gotoNextSlide();
2114 mbWasPaused = false;
2116 else if (rMenuId == u"first")
2118 gotoFirstSlide();
2119 mbWasPaused = false;
2121 else if (rMenuId == u"last")
2123 gotoLastSlide();
2124 mbWasPaused = false;
2126 else if (rMenuId == u"black" || rMenuId == u"white")
2128 const Color aBlankColor(rMenuId == u"white" ? COL_WHITE : COL_BLACK);
2129 if( mbWasPaused )
2131 if( mpShowWindow->GetShowWindowMode() == SHOWWINDOWMODE_BLANK )
2133 if( mpShowWindow->GetBlankColor() == aBlankColor )
2135 mbWasPaused = false;
2136 mpShowWindow->RestartShow();
2137 return;
2140 mpShowWindow->RestartShow();
2142 if( mpShowWindow->SetBlankMode( mpSlideController->getCurrentSlideIndex(), aBlankColor ) )
2144 pause();
2145 mbWasPaused = true;
2148 else if (rMenuId == u"color")
2150 //Open a color picker based on SvColorDialog
2151 ::Color aColor( ColorTransparency, mnUserPaintColor );
2152 SvColorDialog aColorDlg;
2153 aColorDlg.SetColor( aColor );
2155 if (aColorDlg.Execute(mpShowWindow->GetFrameWeld()))
2157 aColor = aColorDlg.GetColor();
2158 setPenColor(sal_Int32(aColor));
2160 mbWasPaused = false;
2162 else if (rMenuId == u"4")
2164 setPenWidth(4.0);
2165 mbWasPaused = false;
2167 else if (rMenuId == u"100")
2169 setPenWidth(100.0);
2170 mbWasPaused = false;
2172 else if (rMenuId == u"150")
2174 setPenWidth(150.0);
2175 mbWasPaused = false;
2177 else if (rMenuId == u"200")
2179 setPenWidth(200.0);
2180 mbWasPaused = false;
2182 else if (rMenuId == u"400")
2184 setPenWidth(400.0);
2185 mbWasPaused = false;
2187 else if (rMenuId == u"erase")
2189 setEraseAllInk(true);
2190 mbWasPaused = false;
2192 else if (rMenuId == u"pen")
2194 setUsePen(!mbUsePen);
2195 mbWasPaused = false;
2197 else if (rMenuId == u"edit")
2199 // When in autoplay mode (pps/ppsx), offer editing of the presentation
2200 // Turn autostart off, else Impress will close when exiting the Presentation
2201 mpViewShell->GetDoc()->SetExitAfterPresenting(false);
2202 if( mpSlideController && (ANIMATIONMODE_SHOW == meAnimationMode) )
2204 if( mpSlideController->getCurrentSlideNumber() != -1 )
2206 mnRestoreSlide = mpSlideController->getCurrentSlideNumber();
2209 endPresentation();
2211 else if (rMenuId == u"end")
2213 // in case the user cancels the presentation, switch to current slide
2214 // in edit mode
2215 if( mpSlideController && (ANIMATIONMODE_SHOW == meAnimationMode) )
2217 if( mpSlideController->getCurrentSlideNumber() != -1 )
2219 mnRestoreSlide = mpSlideController->getCurrentSlideNumber();
2222 endPresentation();
2224 else if (!rMenuId.empty())
2226 sal_Int32 nPageNumber = o3tl::toInt32(rMenuId) - CM_SLIDES;
2227 const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode();
2228 if( (eMode == SHOWWINDOWMODE_END) || (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) )
2230 mpShowWindow->RestartShow( nPageNumber );
2232 else if( nPageNumber != mpSlideController->getCurrentSlideNumber() )
2234 displaySlideNumber( nPageNumber );
2236 mbWasPaused = false;
2240 Reference< XSlideShow > SlideshowImpl::createSlideShow()
2242 Reference< XSlideShow > xShow;
2246 Reference< uno::XComponentContext > xContext =
2247 ::comphelper::getProcessComponentContext();
2249 xShow.set( presentation::SlideShow::create(xContext), UNO_SET_THROW );
2251 catch( uno::Exception& )
2253 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::createSlideShow()" );
2256 return xShow;
2259 void SlideshowImpl::createSlideList( bool bAll, std::u16string_view rPresSlide )
2261 const sal_uInt16 nSlideCount = mpDoc->GetSdPageCount( PageKind::Standard );
2263 if( !nSlideCount )
2264 return;
2266 SdCustomShow* pCustomShow;
2268 if( mpDoc->GetCustomShowList() && maPresSettings.mbCustomShow )
2269 pCustomShow = mpDoc->GetCustomShowList()->GetCurObject();
2270 else
2271 pCustomShow = nullptr;
2273 // create animation slide controller
2274 AnimationSlideController::Mode eMode =
2275 ( pCustomShow && !pCustomShow->PagesVector().empty() ) ? AnimationSlideController::CUSTOM :
2276 (bAll ? AnimationSlideController::ALL : AnimationSlideController::FROM);
2278 Reference< XDrawPagesSupplier > xDrawPages( mpDoc->getUnoModel(), UNO_QUERY_THROW );
2279 Reference< XIndexAccess > xSlides( xDrawPages->getDrawPages(), UNO_QUERY_THROW );
2280 mpSlideController = std::make_shared<AnimationSlideController>( xSlides, eMode );
2282 if( eMode != AnimationSlideController::CUSTOM )
2284 sal_Int32 nFirstVisibleSlide = 0;
2286 // normal presentation
2287 if( !rPresSlide.empty() )
2289 sal_Int32 nSlide;
2290 bool bTakeNextAvailable = false;
2292 for( nSlide = 0, nFirstVisibleSlide = -1;
2293 ( nSlide < nSlideCount ) && ( -1 == nFirstVisibleSlide ); nSlide++ )
2295 SdPage* pTestSlide = mpDoc->GetSdPage( static_cast<sal_uInt16>(nSlide), PageKind::Standard );
2297 if( pTestSlide->GetName() == rPresSlide )
2299 if( pTestSlide->IsExcluded() )
2300 bTakeNextAvailable = true;
2301 else
2302 nFirstVisibleSlide = nSlide;
2304 else if( bTakeNextAvailable && !pTestSlide->IsExcluded() )
2305 nFirstVisibleSlide = nSlide;
2308 if( -1 == nFirstVisibleSlide )
2309 nFirstVisibleSlide = 0;
2312 for( sal_Int32 i = 0; i < nSlideCount; i++ )
2314 bool bVisible = ! mpDoc->GetSdPage( static_cast<sal_uInt16>(i), PageKind::Standard )->IsExcluded();
2315 if( bVisible || (eMode == AnimationSlideController::ALL) )
2316 mpSlideController->insertSlideNumber( i, bVisible );
2319 mpSlideController->setStartSlideNumber( nFirstVisibleSlide );
2321 else
2323 if( meAnimationMode != ANIMATIONMODE_SHOW && !rPresSlide.empty() )
2325 sal_Int32 nSlide;
2326 for( nSlide = 0; nSlide < nSlideCount; nSlide++ )
2327 if( rPresSlide == mpDoc->GetSdPage( static_cast<sal_uInt16>(nSlide), PageKind::Standard )->GetName() )
2328 break;
2330 if( nSlide < nSlideCount )
2331 mpSlideController->insertSlideNumber( static_cast<sal_uInt16>(nSlide) );
2334 for( const auto& rpPage : pCustomShow->PagesVector() )
2336 const sal_uInt16 nSdSlide = ( rpPage->GetPageNum() - 1 ) / 2;
2338 if( ! mpDoc->GetSdPage( nSdSlide, PageKind::Standard )->IsExcluded())
2339 mpSlideController->insertSlideNumber( nSdSlide );
2344 typedef sal_uInt16 (*FncGetChildWindowId)();
2346 const FncGetChildWindowId aShowChildren[] =
2348 &AnimationChildWindow::GetChildWindowId,
2349 &Svx3DChildWindow::GetChildWindowId,
2350 &SvxFontWorkChildWindow::GetChildWindowId,
2351 &SvxColorChildWindow::GetChildWindowId,
2352 &SvxSearchDialogWrapper::GetChildWindowId,
2353 &SvxBmpMaskChildWindow::GetChildWindowId,
2354 &SvxIMapDlgChildWindow::GetChildWindowId,
2355 &SvxHlinkDlgWrapper::GetChildWindowId,
2356 &SfxInfoBarContainerChild::GetChildWindowId
2359 void SlideshowImpl::hideChildWindows()
2361 mnChildMask = 0;
2363 if( ANIMATIONMODE_SHOW != meAnimationMode )
2364 return;
2366 SfxViewFrame* pViewFrame = getViewFrame();
2368 if( !pViewFrame )
2369 return;
2371 for( sal_uLong i = 0; i < SAL_N_ELEMENTS( aShowChildren ); i++ )
2373 const sal_uInt16 nId = ( *aShowChildren[ i ] )();
2375 if( pViewFrame->GetChildWindow( nId ) )
2377 pViewFrame->SetChildWindow( nId, false );
2378 mnChildMask |= ::tools::ULong(1) << i;
2383 void SlideshowImpl::showChildWindows()
2385 if( ANIMATIONMODE_SHOW == meAnimationMode )
2387 SfxViewFrame* pViewFrame = getViewFrame();
2388 if( pViewFrame )
2390 for( sal_uLong i = 0; i < SAL_N_ELEMENTS(aShowChildren); i++ )
2392 if( mnChildMask & ( ::tools::ULong(1) << i ) )
2393 pViewFrame->SetChildWindow( ( *aShowChildren[ i ] )(), true );
2399 SfxViewFrame* SlideshowImpl::getViewFrame() const
2401 return mpViewShell ? mpViewShell->GetViewFrame() : nullptr;
2404 SfxDispatcher* SlideshowImpl::getDispatcher() const
2406 return (mpViewShell && mpViewShell->GetViewFrame()) ? mpViewShell->GetViewFrame()->GetDispatcher() : nullptr;
2409 SfxBindings* SlideshowImpl::getBindings() const
2411 return (mpViewShell && mpViewShell->GetViewFrame()) ? &mpViewShell->GetViewFrame()->GetBindings() : nullptr;
2414 void SlideshowImpl::resize( const Size& rSize )
2416 maPresSize = rSize;
2418 if(mpShowWindow)
2420 mpShowWindow->SetSizePixel( maPresSize );
2421 mpShowWindow->Show();
2424 if( mxView.is() ) try
2426 awt::WindowEvent aEvt;
2427 mxView->windowResized(aEvt);
2429 catch( Exception& )
2431 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::resize()" );
2435 void SlideshowImpl::setActiveXToolbarsVisible( bool bVisible )
2437 // in case of ActiveX control the toolbars should not be visible if slide show runs in window mode
2438 // actually it runs always in window mode in case of ActiveX control
2439 if ( !(!maPresSettings.mbFullScreen && mpDocSh && mpDocSh->GetMedium()) )
2440 return;
2442 const SfxBoolItem* pItem = SfxItemSet::GetItem<SfxBoolItem>(mpDocSh->GetMedium()->GetItemSet(), SID_VIEWONLY, false);
2443 if ( !(pItem && pItem->GetValue()) )
2444 return;
2446 // this is a plugin/activex mode, no toolbars should be visible during slide show
2447 // after the end of slide show they should be visible again
2448 SfxViewFrame* pViewFrame = getViewFrame();
2449 if( !pViewFrame )
2450 return;
2454 Reference< frame::XLayoutManager > xLayoutManager;
2455 Reference< beans::XPropertySet > xFrameProps( pViewFrame->GetFrame().GetFrameInterface(), UNO_QUERY_THROW );
2456 if ( ( xFrameProps->getPropertyValue( "LayoutManager" )
2457 >>= xLayoutManager )
2458 && xLayoutManager.is() )
2460 xLayoutManager->setVisible( bVisible );
2463 catch( uno::Exception& )
2467 void SAL_CALL SlideshowImpl::activate()
2469 SolarMutexGuard aSolarGuard;
2471 maDeactivateTimer.Stop();
2473 if( mbActive || !mxShow.is() )
2474 return;
2476 mbActive = true;
2478 if( ANIMATIONMODE_SHOW == meAnimationMode )
2480 if( mbAutoSaveWasOn )
2481 setAutoSaveState( false );
2483 if( mpShowWindow )
2485 SfxViewFrame* pViewFrame = getViewFrame();
2486 SfxDispatcher* pDispatcher = pViewFrame ? pViewFrame->GetDispatcher() : nullptr;
2488 hideChildWindows();
2490 if( pDispatcher )
2492 // filter all forbidden slots
2493 pDispatcher->SetSlotFilter( SfxSlotFilterState::ENABLED, pAllowed );
2496 if( getBindings() )
2497 getBindings()->InvalidateAll(true);
2499 mpShowWindow->GrabFocus();
2503 resume();
2506 void SAL_CALL SlideshowImpl::deactivate()
2508 SolarMutexGuard aSolarGuard;
2510 if( mbActive && mxShow.is() )
2512 maDeactivateTimer.Start();
2516 IMPL_LINK_NOARG(SlideshowImpl, deactivateHdl, Timer *, void)
2518 if( !(mbActive && mxShow.is()) )
2519 return;
2521 mbActive = false;
2523 pause();
2525 if( ANIMATIONMODE_SHOW == meAnimationMode )
2527 if( mbAutoSaveWasOn )
2528 setAutoSaveState( true );
2530 if( mpShowWindow )
2532 showChildWindows();
2537 sal_Bool SAL_CALL SlideshowImpl::isActive()
2539 SolarMutexGuard aSolarGuard;
2540 return mbActive;
2543 void SlideshowImpl::setAutoSaveState( bool bOn)
2547 uno::Reference<uno::XComponentContext> xContext( ::comphelper::getProcessComponentContext() );
2549 uno::Reference< util::XURLTransformer > xParser(util::URLTransformer::create(xContext));
2550 util::URL aURL;
2551 aURL.Complete = "vnd.sun.star.autorecovery:/setAutoSaveState";
2552 xParser->parseStrict(aURL);
2554 Sequence< beans::PropertyValue > aArgs{ comphelper::makePropertyValue("AutoSaveState", bOn) };
2556 uno::Reference< frame::XDispatch > xAutoSave = frame::theAutoRecovery::get(xContext);
2557 xAutoSave->dispatch(aURL, aArgs);
2559 catch( Exception& )
2561 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::setAutoSaveState()");
2565 Reference< XDrawPage > SAL_CALL SlideshowImpl::getCurrentSlide()
2567 SolarMutexGuard aSolarGuard;
2569 Reference< XDrawPage > xSlide;
2570 if( mxShow.is() && mpSlideController )
2572 sal_Int32 nSlide = getCurrentSlideNumber();
2573 if( (nSlide >= 0) && (nSlide < mpSlideController->getSlideNumberCount() ) )
2574 xSlide = mpSlideController->getSlideByNumber( nSlide );
2577 return xSlide;
2580 sal_Int32 SAL_CALL SlideshowImpl::getNextSlideIndex()
2582 SolarMutexGuard aSolarGuard;
2584 if( mxShow.is() )
2586 return mpSlideController->getNextSlideIndex();
2588 else
2590 return -1;
2594 sal_Int32 SAL_CALL SlideshowImpl::getCurrentSlideIndex()
2596 return mpSlideController ? mpSlideController->getCurrentSlideIndex() : -1;
2599 // css::presentation::XSlideShowController:
2601 ::sal_Int32 SAL_CALL SlideshowImpl::getSlideCount()
2603 return mpSlideController ? mpSlideController->getSlideIndexCount() : 0;
2606 Reference< XDrawPage > SAL_CALL SlideshowImpl::getSlideByIndex(::sal_Int32 Index)
2608 if ((mpSlideController == nullptr) || (Index < 0)
2609 || (Index >= mpSlideController->getSlideIndexCount()))
2610 throw IndexOutOfBoundsException();
2612 return mpSlideController->getSlideByNumber( mpSlideController->getSlideNumber( Index ) );
2615 sal_Bool SAL_CALL SlideshowImpl::getAlwaysOnTop()
2617 SolarMutexGuard aSolarGuard;
2618 return maPresSettings.mbAlwaysOnTop;
2621 void SAL_CALL SlideshowImpl::setAlwaysOnTop( sal_Bool bAlways )
2623 SolarMutexGuard aSolarGuard;
2624 if( maPresSettings.mbAlwaysOnTop != bool(bAlways) )
2626 maPresSettings.mbAlwaysOnTop = bAlways;
2627 // todo, can this be changed while running?
2631 sal_Bool SAL_CALL SlideshowImpl::isFullScreen()
2633 SolarMutexGuard aSolarGuard;
2634 return maPresSettings.mbFullScreen;
2637 sal_Bool SAL_CALL SlideshowImpl::getMouseVisible()
2639 SolarMutexGuard aSolarGuard;
2640 return maPresSettings.mbMouseVisible;
2643 void SAL_CALL SlideshowImpl::setMouseVisible( sal_Bool bVisible )
2645 SolarMutexGuard aSolarGuard;
2646 if( maPresSettings.mbMouseVisible != bool(bVisible) )
2648 maPresSettings.mbMouseVisible = bVisible;
2649 if( mpShowWindow )
2650 mpShowWindow->SetMouseAutoHide( !maPresSettings.mbMouseVisible );
2654 sal_Bool SAL_CALL SlideshowImpl::getUsePen()
2656 SolarMutexGuard aSolarGuard;
2657 return mbUsePen;
2660 void SAL_CALL SlideshowImpl::setUsePen( sal_Bool bMouseAsPen )
2662 SolarMutexGuard aSolarGuard;
2663 mbUsePen = bMouseAsPen;
2664 if( !mxShow.is() )
2665 return;
2669 // For Pencolor;
2670 Any aValue;
2671 if( mbUsePen )
2672 aValue <<= mnUserPaintColor;
2673 beans::PropertyValue aPenProp;
2674 aPenProp.Name = "UserPaintColor";
2675 aPenProp.Value = aValue;
2676 mxShow->setProperty( aPenProp );
2678 //for StrokeWidth :
2679 if( mbUsePen )
2681 beans::PropertyValue aPenPropWidth;
2682 aPenPropWidth.Name = "UserPaintStrokeWidth";
2683 aPenPropWidth.Value <<= mdUserPaintStrokeWidth;
2684 mxShow->setProperty( aPenPropWidth );
2686 // for Pen Mode
2687 beans::PropertyValue aPenPropSwitchPenMode;
2688 aPenPropSwitchPenMode.Name = "SwitchPenMode";
2689 aPenPropSwitchPenMode.Value <<= true;
2690 mxShow->setProperty( aPenPropSwitchPenMode );
2693 catch( Exception& )
2695 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::setUsePen()" );
2699 double SAL_CALL SlideshowImpl::getPenWidth()
2701 SolarMutexGuard aSolarGuard;
2702 return mdUserPaintStrokeWidth;
2705 void SAL_CALL SlideshowImpl::setPenWidth( double dStrokeWidth )
2707 SolarMutexGuard aSolarGuard;
2708 mdUserPaintStrokeWidth = dStrokeWidth;
2709 setUsePen( true ); // enable pen mode, update color and width
2712 sal_Int32 SAL_CALL SlideshowImpl::getPenColor()
2714 SolarMutexGuard aSolarGuard;
2715 return mnUserPaintColor;
2718 void SAL_CALL SlideshowImpl::setPenColor( sal_Int32 nColor )
2720 SolarMutexGuard aSolarGuard;
2721 mnUserPaintColor = nColor;
2722 setUsePen( true ); // enable pen mode, update color
2725 void SAL_CALL SlideshowImpl::setEraseAllInk(sal_Bool bEraseAllInk)
2727 if( !bEraseAllInk )
2728 return;
2730 SolarMutexGuard aSolarGuard;
2731 if( !mxShow.is() )
2732 return;
2736 beans::PropertyValue aPenPropEraseAllInk;
2737 aPenPropEraseAllInk.Name = "EraseAllInk";
2738 aPenPropEraseAllInk.Value <<= bEraseAllInk;
2739 mxShow->setProperty( aPenPropEraseAllInk );
2741 catch( Exception& )
2743 TOOLS_WARN_EXCEPTION( "sd.slideshow", "sd::SlideshowImpl::setEraseAllInk()" );
2747 // XSlideShowController Methods
2748 sal_Bool SAL_CALL SlideshowImpl::isRunning( )
2750 SolarMutexGuard aSolarGuard;
2751 return mxShow.is();
2754 void SAL_CALL SlideshowImpl::gotoNextEffect( )
2756 SolarMutexGuard aSolarGuard;
2758 if( !(mxShow.is() && mpSlideController && mpShowWindow) )
2759 return;
2761 if( mbIsPaused )
2762 resume();
2764 const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode();
2765 if( eMode == SHOWWINDOWMODE_END )
2767 endPresentation();
2769 else if( (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) )
2771 mpShowWindow->RestartShow();
2773 else
2775 mxShow->nextEffect();
2776 update();
2780 void SAL_CALL SlideshowImpl::gotoPreviousEffect( )
2782 SolarMutexGuard aSolarGuard;
2784 if( !(mxShow.is() && mpSlideController && mpShowWindow) )
2785 return;
2787 if( mbIsPaused )
2788 resume();
2790 const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode();
2791 if( (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) )
2793 mpShowWindow->RestartShow();
2795 else
2797 mxShow->previousEffect();
2798 update();
2802 void SAL_CALL SlideshowImpl::gotoFirstSlide( )
2804 SolarMutexGuard aSolarGuard;
2806 if( !(mpShowWindow && mpSlideController) )
2807 return;
2809 if( mbIsPaused )
2810 resume();
2812 if( mpShowWindow->GetShowWindowMode() == SHOWWINDOWMODE_END )
2814 if( mpSlideController->getSlideIndexCount() )
2815 mpShowWindow->RestartShow( 0);
2817 else
2819 displaySlideIndex( 0 );
2823 void SAL_CALL SlideshowImpl::gotoNextSlide( )
2825 SolarMutexGuard aSolarGuard;
2827 if( mbIsPaused )
2828 resume();
2830 const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode();
2831 if( (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) )
2833 mpShowWindow->RestartShow();
2835 else
2837 // if this is a show, ignore user inputs and
2838 // start 20ms timer to reenable inputs to filter
2839 // buffered inputs during slide transition
2840 if( meAnimationMode == ANIMATIONMODE_SHOW )
2842 mbInputFreeze = true;
2843 maInputFreezeTimer.Start();
2846 if( mpSlideController )
2848 if( mpSlideController->nextSlide() )
2850 displayCurrentSlide();
2852 else
2854 stopSound();
2856 if( meAnimationMode == ANIMATIONMODE_PREVIEW )
2858 endPresentation();
2860 else if( maPresSettings.mbEndless )
2862 if( maPresSettings.mnPauseTimeout )
2864 if( mpShowWindow )
2866 if ( maPresSettings.mbShowPauseLogo )
2868 Graphic aGraphic(SfxApplication::GetApplicationLogo(360));
2869 mpShowWindow->SetPauseMode( maPresSettings.mnPauseTimeout, &aGraphic );
2871 else
2872 mpShowWindow->SetPauseMode( maPresSettings.mnPauseTimeout );
2875 else
2877 displaySlideIndex( 0 );
2880 else
2882 if( mpShowWindow )
2884 mpShowWindow->SetEndMode();
2885 if( !mpViewShell->GetDoc()->IsStartWithPresentation() )
2886 pause();
2894 void SAL_CALL SlideshowImpl::gotoPreviousSlide( )
2896 gotoPreviousSlide(false);
2899 void SlideshowImpl::gotoPreviousSlide (const bool bSkipAllMainSequenceEffects)
2901 SolarMutexGuard aSolarGuard;
2903 if( !(mxShow.is() && mpSlideController) )
2904 return;
2908 if( mbIsPaused )
2909 resume();
2911 const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode();
2912 if( eMode == SHOWWINDOWMODE_END )
2914 mpShowWindow->RestartShow( mpSlideController->getCurrentSlideIndex() );
2916 else if( (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) )
2918 mpShowWindow->RestartShow();
2920 else
2922 if( mpSlideController->previousSlide())
2923 displayCurrentSlide(bSkipAllMainSequenceEffects);
2924 else if (bSkipAllMainSequenceEffects)
2926 // We could not go to the previous slide (probably because
2927 // the current slide is already the first one). We still
2928 // have to call displayCurrentSlide because the calling
2929 // slideshow can not determine whether there is a previous
2930 // slide or not and has already prepared for a slide change.
2931 // This slide change has to be completed now, even when
2932 // changing to the same slide.
2933 // Note that in this special case we do NOT pass
2934 // bSkipAllMainSequenceEffects because we display the same
2935 // slide as before and do not want to show all its effects.
2936 displayCurrentSlide();
2940 catch( Exception& )
2942 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::gotoPreviousSlide()" );
2946 void SAL_CALL SlideshowImpl::gotoLastSlide()
2948 SolarMutexGuard aSolarGuard;
2950 if( !mpSlideController )
2951 return;
2953 if( mbIsPaused )
2954 resume();
2956 const sal_Int32 nLastSlideIndex = mpSlideController->getSlideIndexCount() - 1;
2957 if( nLastSlideIndex >= 0 )
2959 if( mpShowWindow->GetShowWindowMode() == SHOWWINDOWMODE_END )
2961 mpShowWindow->RestartShow( nLastSlideIndex );
2963 else
2965 displaySlideIndex( nLastSlideIndex );
2970 void SAL_CALL SlideshowImpl::gotoBookmark( const OUString& rBookmark )
2972 SolarMutexGuard aSolarGuard;
2974 if( mbIsPaused )
2975 resume();
2977 sal_Int32 nSlideNumber = getSlideNumberForBookmark( rBookmark );
2978 if( nSlideNumber != -1 )
2979 displaySlideNumber( nSlideNumber );
2982 void SAL_CALL SlideshowImpl::gotoSlide( const Reference< XDrawPage >& xSlide )
2984 SolarMutexGuard aSolarGuard;
2986 if( !(mpSlideController && xSlide.is()) )
2987 return;
2989 if( mbIsPaused )
2990 resume();
2992 const sal_Int32 nSlideCount = mpSlideController->getSlideNumberCount();
2993 for( sal_Int32 nSlide = 0; nSlide < nSlideCount; nSlide++ )
2995 if( mpSlideController->getSlideByNumber( nSlide ) == xSlide )
2997 displaySlideNumber( nSlide );
3002 void SAL_CALL SlideshowImpl::gotoSlideIndex( sal_Int32 nIndex )
3004 SolarMutexGuard aSolarGuard;
3006 if( mbIsPaused )
3007 resume();
3009 displaySlideIndex( nIndex );
3012 void SAL_CALL SlideshowImpl::stopSound( )
3014 SolarMutexGuard aSolarGuard;
3018 if( mxPlayer.is() )
3020 mxPlayer->stop();
3021 mxPlayer.clear();
3024 catch( Exception& )
3026 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::stopSound()" );
3030 // XIndexAccess
3032 ::sal_Int32 SAL_CALL SlideshowImpl::getCount( )
3034 return getSlideCount();
3037 css::uno::Any SAL_CALL SlideshowImpl::getByIndex( ::sal_Int32 Index )
3039 return Any( getSlideByIndex( Index ) );
3042 css::uno::Type SAL_CALL SlideshowImpl::getElementType( )
3044 return cppu::UnoType<XDrawPage>::get();
3047 sal_Bool SAL_CALL SlideshowImpl::hasElements( )
3049 return getSlideCount() != 0;
3052 Reference< XSlideShow > SAL_CALL SlideshowImpl::getSlideShow()
3054 return mxShow;
3057 PresentationSettingsEx::PresentationSettingsEx( const PresentationSettingsEx& r )
3058 : PresentationSettings( r )
3059 , mbRehearseTimings(r.mbRehearseTimings)
3060 , mbPreview(r.mbPreview)
3061 , mpParentWindow( nullptr )
3065 PresentationSettingsEx::PresentationSettingsEx( PresentationSettings const & r )
3066 : PresentationSettings( r )
3067 , mbRehearseTimings(false)
3068 , mbPreview(false)
3069 , mpParentWindow(nullptr)
3073 void PresentationSettingsEx::SetArguments( const Sequence< PropertyValue >& rArguments )
3075 for( const PropertyValue& rValue : rArguments )
3077 SetPropertyValue( rValue.Name, rValue.Value );
3081 void PresentationSettingsEx::SetPropertyValue( std::u16string_view rProperty, const Any& rValue )
3083 if ( rProperty == u"RehearseTimings" )
3085 if( rValue >>= mbRehearseTimings )
3086 return;
3088 else if ( rProperty == u"Preview" )
3090 if( rValue >>= mbPreview )
3091 return;
3093 else if ( rProperty == u"AnimationNode" )
3095 if( rValue >>= mxAnimationNode )
3096 return;
3098 else if ( rProperty == u"ParentWindow" )
3100 Reference< XWindow > xWindow;
3101 if( rValue >>= xWindow )
3103 mpParentWindow = xWindow.is() ? VCLUnoHelper::GetWindow( xWindow )
3104 : nullptr;
3105 return;
3108 else if ( rProperty == u"AllowAnimations" )
3110 if( rValue >>= mbAnimationAllowed )
3111 return;
3113 else if ( rProperty == u"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 == u"IsAlwaysOnTop" )
3131 if( rValue >>= mbAlwaysOnTop )
3132 return;
3134 else if ( rProperty == u"IsAutomatic" )
3136 if( rValue >>= mbManual )
3137 return;
3139 else if ( rProperty == u"IsEndless" )
3141 if( rValue >>= mbEndless )
3142 return;
3144 else if ( rProperty == u"IsFullScreen" )
3146 if( rValue >>= mbFullScreen )
3147 return;
3149 else if ( rProperty == u"IsMouseVisible" )
3151 if( rValue >>= mbMouseVisible )
3152 return;
3154 else if ( rProperty == u"Pause" )
3156 sal_Int32 nPause = -1;
3157 if( (rValue >>= nPause) && (nPause >= 0) )
3159 mnPauseTimeout = nPause;
3160 return;
3163 else if ( rProperty == u"UsePen" )
3165 if( rValue >>= mbMouseAsPen )
3166 return;
3168 throw IllegalArgumentException();
3171 // XAnimationListener
3173 SlideShowListenerProxy::SlideShowListenerProxy( rtl::Reference< SlideshowImpl > xController, css::uno::Reference< css::presentation::XSlideShow > xSlideShow )
3174 : mxController(std::move( xController ))
3175 , mxSlideShow(std::move( xSlideShow ))
3179 SlideShowListenerProxy::~SlideShowListenerProxy()
3183 void SlideShowListenerProxy::addAsSlideShowListener()
3185 if( mxSlideShow.is() )
3187 Reference< XSlideShowListener > xSlideShowListener( this );
3188 mxSlideShow->addSlideShowListener( xSlideShowListener );
3192 void SlideShowListenerProxy::removeAsSlideShowListener()
3194 if( mxSlideShow.is() )
3196 Reference< XSlideShowListener > xSlideShowListener( this );
3197 mxSlideShow->removeSlideShowListener( xSlideShowListener );
3201 void SlideShowListenerProxy::addShapeEventListener( const css::uno::Reference< css::drawing::XShape >& xShape )
3203 if( mxSlideShow.is() )
3205 Reference< XShapeEventListener > xListener( this );
3206 mxSlideShow->addShapeEventListener( xListener, xShape );
3210 void SlideShowListenerProxy::removeShapeEventListener( const css::uno::Reference< css::drawing::XShape >& xShape )
3212 if( mxSlideShow.is() )
3214 Reference< XShapeEventListener > xListener( this );
3215 mxSlideShow->removeShapeEventListener( xListener, xShape );
3219 void SlideShowListenerProxy::addSlideShowListener( const css::uno::Reference< css::presentation::XSlideShowListener >& xListener )
3221 std::unique_lock g(m_aMutex);
3222 maListeners.addInterface(g, xListener);
3225 void SlideShowListenerProxy::removeSlideShowListener( const css::uno::Reference< css::presentation::XSlideShowListener >& xListener )
3227 std::unique_lock g(m_aMutex);
3228 maListeners.removeInterface(g, xListener);
3231 void SAL_CALL SlideShowListenerProxy::beginEvent( const Reference< XAnimationNode >& xNode )
3233 std::unique_lock aGuard( m_aMutex );
3235 if( maListeners.getLength(aGuard) >= 0 )
3237 maListeners.forEach(aGuard,
3238 [&] (Reference<XAnimationListener> const& xListener) {
3239 return xListener->beginEvent(xNode);
3240 } );
3244 void SAL_CALL SlideShowListenerProxy::endEvent( const Reference< XAnimationNode >& xNode )
3246 std::unique_lock aGuard( m_aMutex );
3248 if( maListeners.getLength(aGuard) >= 0 )
3250 maListeners.forEach(aGuard,
3251 [&] (Reference<XAnimationListener> const& xListener) {
3252 return xListener->endEvent(xNode);
3253 } );
3257 void SAL_CALL SlideShowListenerProxy::repeat( const Reference< XAnimationNode >& xNode, ::sal_Int32 nRepeat )
3259 std::unique_lock aGuard( m_aMutex );
3261 if( maListeners.getLength(aGuard) >= 0 )
3263 maListeners.forEach(aGuard,
3264 [&] (Reference<XAnimationListener> const& xListener) {
3265 return xListener->repeat(xNode, nRepeat);
3266 } );
3270 // css::presentation::XSlideShowListener:
3272 void SAL_CALL SlideShowListenerProxy::paused( )
3274 std::unique_lock aGuard( m_aMutex );
3276 maListeners.forEach(aGuard,
3277 [](uno::Reference<presentation::XSlideShowListener> const& xListener)
3279 xListener->paused();
3283 void SAL_CALL SlideShowListenerProxy::resumed( )
3285 std::unique_lock aGuard( m_aMutex );
3287 maListeners.forEach(aGuard,
3288 [](uno::Reference<presentation::XSlideShowListener> const& xListener)
3290 xListener->resumed();
3294 void SAL_CALL SlideShowListenerProxy::slideTransitionStarted( )
3296 std::unique_lock aGuard( m_aMutex );
3298 maListeners.forEach(aGuard,
3299 [](uno::Reference<presentation::XSlideShowListener> const& xListener)
3301 xListener->slideTransitionStarted();
3305 void SAL_CALL SlideShowListenerProxy::slideTransitionEnded( )
3307 std::unique_lock aGuard( m_aMutex );
3309 maListeners.forEach(aGuard,
3310 [](uno::Reference<presentation::XSlideShowListener> const& xListener)
3312 xListener->slideTransitionEnded ();
3316 void SAL_CALL SlideShowListenerProxy::slideAnimationsEnded( )
3318 std::unique_lock aGuard( m_aMutex );
3320 maListeners.forEach(aGuard,
3321 [](uno::Reference<presentation::XSlideShowListener> const& xListener)
3323 xListener->slideAnimationsEnded ();
3327 void SlideShowListenerProxy::slideEnded(sal_Bool bReverse)
3330 std::unique_lock aGuard( m_aMutex );
3332 if( maListeners.getLength(aGuard) >= 0 )
3334 maListeners.forEach(aGuard,
3335 [&] (Reference<XSlideShowListener> const& xListener) {
3336 return xListener->slideEnded(bReverse);
3337 } );
3342 SolarMutexGuard aSolarGuard;
3343 if( mxController.is() )
3344 mxController->slideEnded(bReverse);
3348 void SlideShowListenerProxy::hyperLinkClicked( OUString const& aHyperLink )
3351 std::unique_lock aGuard( m_aMutex );
3353 if( maListeners.getLength(aGuard) >= 0 )
3355 maListeners.forEach(aGuard,
3356 [&] (Reference<XSlideShowListener> const& xListener) {
3357 return xListener->hyperLinkClicked(aHyperLink);
3358 } );
3363 SolarMutexGuard aSolarGuard;
3364 if( mxController.is() )
3365 mxController->hyperLinkClicked(aHyperLink);
3369 // XEventListener
3371 void SAL_CALL SlideShowListenerProxy::disposing( const css::lang::EventObject& aDisposeEvent )
3373 std::unique_lock g(m_aMutex);
3374 maListeners.disposeAndClear( g, aDisposeEvent );
3375 mxController.clear();
3376 mxSlideShow.clear();
3379 // XShapeEventListener
3381 void SAL_CALL SlideShowListenerProxy::click( const Reference< XShape >& xShape, const css::awt::MouseEvent& /*aOriginalEvent*/ )
3383 SolarMutexGuard aSolarGuard;
3384 if( mxController.is() )
3385 mxController->click(xShape );
3388 void SAL_CALL SlideShowListenerProxy::contextMenuShow(const css::awt::Point& point)
3390 SolarMutexGuard aSolarGuard;
3391 if (mxController.is())
3392 mxController->contextMenuShow(point);
3395 } // namespace ::sd
3397 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */