tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / sd / source / ui / slideshow / slideshowimpl.cxx
blobfd7384f379bbed943c8e79df4757cb2bb576eaaa
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/Impress.hxx>
41 #include <officecfg/Office/Recovery.hxx>
42 #include <svl/stritem.hxx>
43 #include <svl/urihelper.hxx>
44 #include <basic/sbstar.hxx>
46 #include <toolkit/helper/vclunohelper.hxx>
47 #include <comphelper/diagnose_ex.hxx>
48 #include <comphelper/sequence.hxx>
50 #include <sfx2/infobar.hxx>
51 #include <sfx2/dispatch.hxx>
52 #include <sfx2/docfile.hxx>
53 #include <sfx2/app.hxx>
54 #include <sfx2/viewfrm.hxx>
55 #include <svx/svdoole2.hxx>
56 #include <svx/f3dchild.hxx>
57 #include <svx/imapdlg.hxx>
58 #include <svx/fontwork.hxx>
59 #include <svx/SvxColorChildWindow.hxx>
60 #include <svx/bmpmask.hxx>
61 #include <svx/srchdlg.hxx>
62 #include <svx/hyperdlg.hxx>
63 #include <svx/svxids.hrc>
64 #include <svx/unoapi.hxx>
65 #include <AnimationChildWindow.hxx>
66 #include <notifydocumentevent.hxx>
67 #include "slideshowimpl.hxx"
68 #include "slideshowviewimpl.hxx"
69 #include "PaneHider.hxx"
71 #include <bitmaps.hlst>
72 #include <strings.hrc>
73 #include <sdresid.hxx>
74 #include <utility>
75 #include <vcl/canvastools.hxx>
76 #include <vcl/commandevent.hxx>
77 #include <vcl/weldutils.hxx>
79 #include <vcl/settings.hxx>
80 #include <vcl/svapp.hxx>
81 #include <vcl/help.hxx>
82 #include <comphelper/processfactory.hxx>
83 #include <comphelper/propertyvalue.hxx>
84 #include <rtl/ref.hxx>
85 #include <o3tl/safeint.hxx>
86 #include <o3tl/string_view.hxx>
87 #include <avmedia/mediawindow.hxx>
88 #include <svtools/colrdlg.hxx>
89 #include <DrawDocShell.hxx>
90 #include <ViewShellBase.hxx>
91 #include <PresentationViewShell.hxx>
92 #include <RemoteServer.hxx>
93 #include <customshowlist.hxx>
94 #include <unopage.hxx>
95 #include <sdpage.hxx>
96 #include <sdmod.hxx>
97 #include <app.hrc>
98 #include <cusshow.hxx>
99 #include <optsitem.hxx>
100 #include <unomodel.hxx>
102 #define CM_SLIDES 21
104 using ::com::sun::star::animations::XAnimationNode;
105 using ::com::sun::star::animations::XAnimationListener;
106 using ::com::sun::star::awt::XWindow;
107 using namespace ::com::sun::star;
108 using namespace ::com::sun::star::lang;
109 using namespace ::com::sun::star::uno;
110 using namespace ::com::sun::star::drawing;
111 using namespace ::com::sun::star::container;
112 using namespace ::com::sun::star::presentation;
113 using namespace ::com::sun::star::beans;
115 namespace sd
117 /** Slots, which will be disabled in the slide show and are managed by Sfx.
118 Have to be sorted in the order of the SIDs */
119 sal_uInt16 const pAllowed[] =
121 SID_OPENDOC , // 5501 ///< that internally jumps work
122 SID_JUMPTOMARK , // 5598
123 SID_OPENHYPERLINK , // 6676
124 SID_PRESENTATION_END // 27218
127 class AnimationSlideController
129 public:
130 enum Mode { ALL, FROM, CUSTOM, PREVIEW };
132 public:
133 AnimationSlideController( Reference< XIndexAccess > const & xSlides, Mode eMode );
135 void setStartSlideNumber( sal_Int32 nSlideNumber ) { mnStartSlideNumber = nSlideNumber; }
136 sal_Int32 getStartSlideIndex() const;
138 sal_Int32 getCurrentSlideNumber() const;
139 sal_Int32 getCurrentSlideIndex() const;
141 sal_Int32 getSlideIndexCount() const { return maSlideNumbers.size(); }
142 sal_Int32 getSlideNumberCount() const { return mnSlideCount; }
144 sal_Int32 getSlideNumber( sal_Int32 nSlideIndex ) const;
146 void insertSlideNumber( sal_Int32 nSlideNumber, bool bVisible = true );
147 void setPreviewNode( const Reference< XAnimationNode >& xPreviewNode );
149 bool jumpToSlideIndex( sal_Int32 nNewSlideIndex );
150 bool jumpToSlideNumber( sal_Int32 nNewSlideIndex );
152 bool nextSlide();
153 bool previousSlide();
155 void displayCurrentSlide( const Reference< XSlideShow >& xShow,
156 const Reference< XDrawPagesSupplier>& xDrawPages,
157 const bool bSkipAllMainSequenceEffects );
159 sal_Int32 getNextSlideIndex() const;
160 sal_Int32 getPreviousSlideIndex() const;
162 bool isVisibleSlideNumber( sal_Int32 nSlideNumber ) const;
164 Reference< XDrawPage > getSlideByNumber( sal_Int32 nSlideNumber ) const;
166 sal_Int32 getNextSlideNumber() const;
168 bool hasSlides() const { return !maSlideNumbers.empty(); }
170 // for InteractiveSlideShow we need to temporarily change the program
171 // and mode, so allow save/restore that settings
172 void pushForPreview();
173 void popFromPreview();
174 private:
175 bool getSlideAPI( sal_Int32 nSlideNumber, Reference< XDrawPage >& xSlide, Reference< XAnimationNode >& xAnimNode );
176 sal_Int32 findSlideIndex( sal_Int32 nSlideNumber ) const;
178 bool isValidIndex( sal_Int32 nIndex ) const { return (nIndex >= 0) && (o3tl::make_unsigned(nIndex) < maSlideNumbers.size()); }
179 bool isValidSlideNumber( sal_Int32 nSlideNumber ) const { return (nSlideNumber >= 0) && (nSlideNumber < mnSlideCount); }
181 private:
182 Mode meMode;
183 sal_Int32 mnStartSlideNumber;
184 std::vector< sal_Int32 > maSlideNumbers;
185 std::vector< bool > maSlideVisible;
186 std::vector< bool > maSlideVisited;
187 Reference< XAnimationNode > mxPreviewNode;
188 sal_Int32 mnSlideCount;
189 sal_Int32 mnCurrentSlideIndex;
190 sal_Int32 mnHiddenSlideNumber;
191 Reference< XIndexAccess > mxSlides;
193 // IASS data for push/pop
194 std::vector< sal_Int32 > maSlideNumbers2;
195 std::vector< bool > maSlideVisible2;
196 std::vector< bool > maSlideVisited2;
197 Reference< XAnimationNode > mxPreviewNode2;
198 Mode meMode2;
201 void AnimationSlideController::pushForPreview()
203 maSlideNumbers2 = maSlideNumbers;
204 maSlideVisible2 = maSlideVisible;
205 maSlideVisited2 = maSlideVisited;
206 maSlideNumbers.clear();
207 maSlideVisible.clear();
208 maSlideVisited.clear();
209 mxPreviewNode2 = mxPreviewNode;
210 meMode2 = meMode;
211 meMode = AnimationSlideController::PREVIEW;
214 void AnimationSlideController::popFromPreview()
216 maSlideNumbers = maSlideNumbers2;
217 maSlideVisible = maSlideVisible2;
218 maSlideVisited = maSlideVisited2;
219 maSlideNumbers2.clear();
220 maSlideVisible2.clear();
221 maSlideVisited2.clear();
222 mxPreviewNode = mxPreviewNode2;
223 meMode = meMode2;
226 Reference< XDrawPage > AnimationSlideController::getSlideByNumber( sal_Int32 nSlideNumber ) const
228 Reference< XDrawPage > xSlide;
229 if( mxSlides.is() && (nSlideNumber >= 0) && (nSlideNumber < mxSlides->getCount()) )
230 mxSlides->getByIndex( nSlideNumber ) >>= xSlide;
231 return xSlide;
234 bool AnimationSlideController::isVisibleSlideNumber( sal_Int32 nSlideNumber ) const
236 sal_Int32 nIndex = findSlideIndex( nSlideNumber );
238 if( nIndex != -1 )
239 return maSlideVisible[ nIndex ];
240 else
241 return false;
244 void AnimationSlideController::setPreviewNode( const Reference< XAnimationNode >& xPreviewNode )
246 mxPreviewNode = xPreviewNode;
249 AnimationSlideController::AnimationSlideController( Reference< XIndexAccess > const & xSlides, Mode eMode )
250 : meMode( eMode )
251 , mnStartSlideNumber(-1)
252 , mnSlideCount( 0 )
253 , mnCurrentSlideIndex(0)
254 , mnHiddenSlideNumber( -1 )
255 , mxSlides( xSlides )
256 , meMode2( eMode )
258 if( mxSlides.is() )
259 mnSlideCount = xSlides->getCount();
262 sal_Int32 AnimationSlideController::getStartSlideIndex() const
264 if( mnStartSlideNumber >= 0 )
266 sal_Int32 nIndex;
267 const sal_Int32 nCount = maSlideNumbers.size();
269 for( nIndex = 0; nIndex < nCount; nIndex++ )
271 if( maSlideNumbers[nIndex] == mnStartSlideNumber )
272 return nIndex;
276 return 0;
279 sal_Int32 AnimationSlideController::getCurrentSlideNumber() const
281 if( mnHiddenSlideNumber != -1 )
282 return mnHiddenSlideNumber;
283 else if( !maSlideNumbers.empty() )
284 return maSlideNumbers[mnCurrentSlideIndex];
285 else
286 return 0;
289 sal_Int32 AnimationSlideController::getCurrentSlideIndex() const
291 if( mnHiddenSlideNumber != -1 )
292 return -1;
293 else
294 return mnCurrentSlideIndex;
297 bool AnimationSlideController::jumpToSlideIndex( sal_Int32 nNewSlideIndex )
299 if( isValidIndex( nNewSlideIndex ) )
301 mnCurrentSlideIndex = nNewSlideIndex;
302 mnHiddenSlideNumber = -1;
303 maSlideVisited[mnCurrentSlideIndex] = true;
304 return true;
306 else
308 return false;
312 bool AnimationSlideController::jumpToSlideNumber( sal_Int32 nNewSlideNumber )
314 sal_Int32 nIndex = findSlideIndex( nNewSlideNumber );
315 if( isValidIndex( nIndex ) )
317 return jumpToSlideIndex( nIndex );
319 else if( (nNewSlideNumber >= 0) && (nNewSlideNumber < mnSlideCount) )
321 // jump to a hidden slide
322 mnHiddenSlideNumber = nNewSlideNumber;
323 return true;
325 else
327 return false;
331 sal_Int32 AnimationSlideController::getSlideNumber( sal_Int32 nSlideIndex ) const
333 if( isValidIndex( nSlideIndex ) )
334 return maSlideNumbers[nSlideIndex];
335 else
336 return -1;
339 void AnimationSlideController::insertSlideNumber( sal_Int32 nSlideNumber, bool bVisible /* = true */ )
341 DBG_ASSERT( isValidSlideNumber( nSlideNumber ), "sd::AnimationSlideController::insertSlideNumber(), illegal index" );
342 if( isValidSlideNumber( nSlideNumber ) )
344 maSlideNumbers.push_back( nSlideNumber );
345 maSlideVisible.push_back( bVisible );
346 maSlideVisited.push_back( false );
350 bool AnimationSlideController::getSlideAPI( sal_Int32 nSlideNumber, Reference< XDrawPage >& xSlide, Reference< XAnimationNode >& xAnimNode )
352 if( isValidSlideNumber( nSlideNumber ) ) try
354 xSlide.set( mxSlides->getByIndex(nSlideNumber), UNO_QUERY_THROW );
356 if( meMode == PREVIEW )
358 xAnimNode = mxPreviewNode;
360 else
362 Reference< animations::XAnimationNodeSupplier > xAnimNodeSupplier( xSlide, UNO_QUERY_THROW );
363 xAnimNode = xAnimNodeSupplier->getAnimationNode();
366 return true;
368 catch( Exception& )
370 TOOLS_WARN_EXCEPTION( "sd", "sd::AnimationSlideController::getSlideAPI()" );
373 return false;
376 sal_Int32 AnimationSlideController::findSlideIndex( sal_Int32 nSlideNumber ) const
378 sal_Int32 nIndex;
379 const sal_Int32 nCount = maSlideNumbers.size();
381 for( nIndex = 0; nIndex < nCount; nIndex++ )
383 if( maSlideNumbers[nIndex] == nSlideNumber )
384 return nIndex;
387 return -1;
390 sal_Int32 AnimationSlideController::getNextSlideIndex() const
392 switch( meMode )
394 case ALL:
396 sal_Int32 nNewSlideIndex = mnCurrentSlideIndex + 1;
397 if( isValidIndex( nNewSlideIndex ) )
399 // if the current slide is not excluded, make sure the
400 // next slide is also not excluded.
401 // if the current slide is excluded, we want to go
402 // to the next slide, even if this is also excluded.
403 if( maSlideVisible[mnCurrentSlideIndex] )
405 while( isValidIndex( nNewSlideIndex ) )
407 if( maSlideVisible[nNewSlideIndex] )
408 break;
410 nNewSlideIndex++;
414 return isValidIndex( nNewSlideIndex ) ? nNewSlideIndex : -1;
417 case FROM:
418 case CUSTOM:
419 return mnHiddenSlideNumber == -1 ? mnCurrentSlideIndex + 1 : mnCurrentSlideIndex;
421 default:
422 case PREVIEW:
423 return -1;
428 sal_Int32 AnimationSlideController::getNextSlideNumber() const
430 sal_Int32 nNextSlideIndex = getNextSlideIndex();
431 if( isValidIndex( nNextSlideIndex ) )
433 return maSlideNumbers[nNextSlideIndex];
435 else
437 return -1;
441 bool AnimationSlideController::nextSlide()
443 return jumpToSlideIndex( getNextSlideIndex() );
446 sal_Int32 AnimationSlideController::getPreviousSlideIndex() const
448 sal_Int32 nNewSlideIndex = mnCurrentSlideIndex - 1;
450 switch( meMode )
452 case ALL:
454 // make sure the previous slide is visible
455 // or was already visited
456 while( isValidIndex( nNewSlideIndex ) )
458 if( maSlideVisible[nNewSlideIndex] || maSlideVisited[nNewSlideIndex] )
459 break;
461 nNewSlideIndex--;
464 break;
467 case PREVIEW:
468 return -1;
470 default:
471 break;
474 return nNewSlideIndex;
477 bool AnimationSlideController::previousSlide()
479 return jumpToSlideIndex( getPreviousSlideIndex() );
482 void AnimationSlideController::displayCurrentSlide( const Reference< XSlideShow >& xShow,
483 const Reference< XDrawPagesSupplier>& xDrawPages,
484 const bool bSkipAllMainSequenceEffects )
486 const sal_Int32 nCurrentSlideNumber = getCurrentSlideNumber();
488 if( !(xShow.is() && (nCurrentSlideNumber != -1 )) )
489 return;
491 Reference< XDrawPage > xSlide;
492 Reference< XAnimationNode > xAnimNode;
493 ::std::vector<PropertyValue> aProperties;
495 const sal_Int32 nNextSlideNumber = getNextSlideNumber();
496 if( getSlideAPI( nNextSlideNumber, xSlide, xAnimNode ) )
498 Sequence< Any > aValue{ Any(xSlide), Any(xAnimNode) };
499 aProperties.emplace_back( "Prefetch" ,
501 Any(aValue),
502 PropertyState_DIRECT_VALUE);
504 if (bSkipAllMainSequenceEffects)
506 // Add one property that prevents the slide transition from being
507 // shown (to speed up the transition to the previous slide) and
508 // one to show all main sequence effects so that the user can
509 // continue to undo effects.
510 aProperties.emplace_back( "SkipAllMainSequenceEffects",
512 Any(true),
513 PropertyState_DIRECT_VALUE);
514 aProperties.emplace_back("SkipSlideTransition",
516 Any(true),
517 PropertyState_DIRECT_VALUE);
520 if( getSlideAPI( nCurrentSlideNumber, xSlide, xAnimNode ) )
521 xShow->displaySlide( xSlide, xDrawPages, xAnimNode, comphelper::containerToSequence(aProperties) );
524 constexpr OUString gsOnClick( u"OnClick"_ustr );
525 constexpr OUString gsBookmark( u"Bookmark"_ustr );
526 constexpr OUString gsVerb( u"Verb"_ustr );
528 SlideshowImpl::SlideshowImpl( const Reference< XPresentation2 >& xPresentation, ViewShell* pViewSh, ::sd::View* pView, SdDrawDocument* pDoc, vcl::Window* pParentWindow )
529 : mxShow()
530 , mxView()
531 , mxModel(pDoc->getUnoModel())
532 , maUpdateTimer("SlideShowImpl maUpdateTimer")
533 , maInputFreezeTimer("SlideShowImpl maInputFreezeTimer")
534 , maDeactivateTimer("SlideShowImpl maDeactivateTimer")
535 , mpView(pView)
536 , mpViewShell(pViewSh)
537 , mpDocSh(pDoc->GetDocSh())
538 , mpDoc(pDoc)
539 , mpParentWindow(pParentWindow)
540 , mpShowWindow(nullptr)
541 , mpSlideController()
542 , mnRestoreSlide(0)
543 , maPopupMousePos()
544 , maPresSize( -1, -1 )
545 , meAnimationMode(ANIMATIONMODE_SHOW)
546 , maCharBuffer()
547 , mpOldActiveWindow(nullptr)
548 , maStarBASICGlobalErrorHdl()
549 , mnChildMask( 0 )
550 , mbDisposed(false)
551 , mbAutoSaveWasOn(false)
552 , mbRehearseTimings(false)
553 , mbIsPaused(false)
554 , mbWasPaused(false)
555 , mbInputFreeze(false)
556 , mbActive(false)
557 , maPresSettings( pDoc->getPresentationSettings() )
558 , mnUserPaintColor( 0x80ff0000L )
559 , mbUsePen(false)
560 , mdUserPaintStrokeWidth ( 150.0 )
561 , maShapeEventMap()
562 , mxPreviewDrawPage()
563 , mxPreviewAnimationNode()
564 , mxPlayer()
565 , mpPaneHider()
566 , mnEndShowEvent(nullptr)
567 , mnContextMenuEvent(nullptr)
568 , mnEventObjectChange(nullptr)
569 , mnEventObjectInserted(nullptr)
570 , mnEventObjectRemoved(nullptr)
571 , mnEventPageOrderChange(nullptr)
572 , mxPresentation( xPresentation )
573 , mxListenerProxy()
574 , mxShow2()
575 , mxView2()
576 , meAnimationMode2()
577 , mbInterActiveSetup(false)
578 , maPresSettings2()
579 , mxPreviewDrawPage2()
580 , mxPreviewAnimationNode2()
581 , mnSlideIndex(0)
583 if( mpViewShell )
584 mpOldActiveWindow = mpViewShell->GetActiveWindow();
586 maUpdateTimer.SetInvokeHandler(LINK(this, SlideshowImpl, updateHdl));
587 // Priority must not be too high or we'll starve input handling etc.
588 maUpdateTimer.SetPriority(TaskPriority::REPAINT);
590 maDeactivateTimer.SetInvokeHandler(LINK(this, SlideshowImpl, deactivateHdl));
591 maDeactivateTimer.SetTimeout( 20 );
593 maInputFreezeTimer.SetInvokeHandler( LINK( this, SlideshowImpl, ReadyForNextInputHdl ) );
594 maInputFreezeTimer.SetTimeout( 20 );
596 // no autosave during show
597 if (officecfg::Office::Recovery::AutoSave::Enabled::get())
598 mbAutoSaveWasOn = true;
600 Application::AddEventListener( LINK( this, SlideshowImpl, EventListenerHdl ) );
602 mbUsePen = maPresSettings.mbMouseAsPen;
604 SdOptions* pOptions = SdModule::get()->GetSdOptions(DocumentType::Impress);
605 if( pOptions )
607 mnUserPaintColor = pOptions->GetPresentationPenColor();
608 mdUserPaintStrokeWidth = pOptions->GetPresentationPenWidth();
611 // to be able to react on various changes in the DrawModel, this class
612 // is now derived from SfxListener and registers itself at the DrawModel
613 if (nullptr != mpDoc)
614 StartListening(*mpDoc);
617 SlideshowImpl::~SlideshowImpl()
619 // stop listening to DrawModel (see above)
620 if (nullptr != mpDoc)
621 EndListening(*mpDoc);
623 SdModule* pModule = SdModule::get();
624 //rhbz#806663 SlideshowImpl can outlive SdModule
625 SdOptions* pOptions = pModule ?
626 pModule->GetSdOptions(DocumentType::Impress) : nullptr;
627 if( pOptions )
629 pOptions->SetPresentationPenColor(mnUserPaintColor);
630 pOptions->SetPresentationPenWidth(mdUserPaintStrokeWidth);
633 Application::RemoveEventListener( LINK( this, SlideshowImpl, EventListenerHdl ) );
635 maDeactivateTimer.Stop();
637 if( !mbDisposed )
639 OSL_FAIL("SlideshowImpl::~SlideshowImpl(), component was not disposed!");
640 std::unique_lock g(m_aMutex);
641 disposing(g);
645 void SlideshowImpl::disposing(std::unique_lock<std::mutex>&)
647 #ifdef ENABLE_SDREMOTE
648 RemoteServer::presentationStopped();
649 #endif
650 // IASS: This is the central methodology to 'steer' the
651 // PresenterConsole - in this case, to shut it down
652 if( mxShow.is() && mpDoc )
653 NotifyDocumentEvent(
654 *mpDoc,
655 u"OnEndPresentation"_ustr );
657 if( mbAutoSaveWasOn )
658 setAutoSaveState( true );
660 if( mnEndShowEvent )
661 Application::RemoveUserEvent( mnEndShowEvent );
662 if( mnContextMenuEvent )
663 Application::RemoveUserEvent( mnContextMenuEvent );
664 if( mnEventObjectChange )
665 Application::RemoveUserEvent( mnEventObjectChange );
666 if( mnEventObjectInserted )
667 Application::RemoveUserEvent( mnEventObjectInserted );
668 if( mnEventObjectRemoved )
669 Application::RemoveUserEvent( mnEventObjectRemoved );
670 if( mnEventPageOrderChange )
671 Application::RemoveUserEvent( mnEventPageOrderChange );
673 maInputFreezeTimer.Stop();
675 SolarMutexGuard aSolarGuard;
677 if( !mxShow.is() )
678 return;
680 if( mxPresentation.is() )
681 mxPresentation->end();
683 maUpdateTimer.Stop();
685 removeShapeEvents();
687 if( mxListenerProxy.is() )
688 mxListenerProxy->removeAsSlideShowListener();
692 if( mxView.is() )
693 mxShow->removeView( mxView );
695 Reference< XComponent > xComponent( mxShow, UNO_QUERY );
696 if( xComponent.is() )
697 xComponent->dispose();
699 if( mxView.is() )
700 mxView->dispose();
702 catch( Exception& )
704 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::stop()" );
707 mxShow.clear();
708 mxView.clear();
709 mxListenerProxy.clear();
710 mpSlideController.reset();
712 // take DrawView from presentation window, but give the old window back
713 if( mpShowWindow && mpView )
714 mpView->DeleteDeviceFromPaintView( *mpShowWindow->GetOutDev() );
716 if( mpView )
717 mpView->SetAnimationPause( false );
719 if( mpViewShell )
721 mpViewShell->SetActiveWindow(mpOldActiveWindow);
722 if (mpShowWindow)
723 mpShowWindow->SetViewShell( nullptr );
726 if( mpView )
727 mpView->InvalidateAllWin();
729 if( maPresSettings.mbFullScreen )
731 #if HAVE_FEATURE_SCRIPTING
732 // restore StarBASICErrorHdl
733 StarBASIC::SetGlobalErrorHdl(maStarBASICGlobalErrorHdl);
734 maStarBASICGlobalErrorHdl = Link<StarBASIC*,bool>();
735 #endif
737 else
739 if( mpShowWindow )
740 mpShowWindow->Hide();
743 if( meAnimationMode == ANIMATIONMODE_SHOW )
745 mpDocSh->SetSlotFilter();
746 mpDocSh->ApplySlotFilter();
748 Help::EnableContextHelp();
749 Help::EnableExtHelp();
751 showChildWindows();
752 mnChildMask = 0;
755 // show current window again
756 if( mpViewShell && dynamic_cast< PresentationViewShell *>( mpViewShell ) == nullptr)
758 if( meAnimationMode == ANIMATIONMODE_SHOW )
760 mpViewShell->GetViewShellBase().ShowUIControls (true);
761 mpPaneHider.reset();
763 else if( meAnimationMode == ANIMATIONMODE_PREVIEW )
765 mpViewShell->ShowUIControls(true);
769 if( mpShowWindow )
770 mpShowWindow->Hide();
771 mpShowWindow.disposeAndClear();
773 if ( mpViewShell )
775 if( meAnimationMode == ANIMATIONMODE_SHOW )
777 ::sd::Window* pActWin = mpViewShell->GetActiveWindow();
779 if (pActWin)
781 Size aVisSizePixel = pActWin->GetOutputSizePixel();
782 ::tools::Rectangle aVisAreaWin = pActWin->PixelToLogic( ::tools::Rectangle( Point(0,0), aVisSizePixel) );
783 mpViewShell->VisAreaChanged(aVisAreaWin);
784 if (mpView)
785 mpView->VisAreaChanged(pActWin->GetOutDev());
786 pActWin->GrabFocus();
790 // restart the custom show dialog if he started us
791 if( mpViewShell->IsStartShowWithDialog() && getDispatcher() )
793 mpViewShell->SetStartShowWithDialog( false );
794 getDispatcher()->Execute( SID_CUSTOMSHOW_DLG, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD );
797 mpViewShell->GetViewShellBase().UpdateBorder(true);
800 if( mpShowWindow )
802 mpShowWindow.disposeAndClear();
805 setActiveXToolbarsVisible( true );
807 mbDisposed = true;
810 bool SlideshowImpl::isInteractiveSetup() const
812 return mbInterActiveSetup;
815 void SlideshowImpl::startInteractivePreview( const Reference< XDrawPage >& xDrawPage, const Reference< XAnimationNode >& xAnimationNode )
817 // set flag that we are in IASS mode
818 mbInterActiveSetup = true;
820 // save stuff that will be replaced temporarily
821 mxShow2 = mxShow;
822 mxView2 = mxView;
823 mxPreviewDrawPage2 = mxPreviewDrawPage;
824 mxPreviewAnimationNode2 = mxPreviewAnimationNode;
825 meAnimationMode2 = meAnimationMode;
826 maPresSettings2 = maPresSettings;
828 // remember slide shown before preview
829 mnSlideIndex = getCurrentSlideIndex();
831 // set DrawPage/AnimationNode
832 mxPreviewDrawPage = xDrawPage;
833 mxPreviewAnimationNode = xAnimationNode;
834 meAnimationMode = ANIMATIONMODE_PREVIEW;
836 // set PresSettings for preview
837 maPresSettings.mbAll = false;
838 maPresSettings.mbEndless = false;
839 maPresSettings.mbCustomShow = false;
840 maPresSettings.mbManual = false;
841 maPresSettings.mbMouseVisible = false;
842 maPresSettings.mbMouseAsPen = false;
843 maPresSettings.mbLockedPages = false;
844 maPresSettings.mbAlwaysOnTop = false;
845 maPresSettings.mbFullScreen = false;
846 maPresSettings.mbAnimationAllowed = true;
847 maPresSettings.mnPauseTimeout = 0;
848 maPresSettings.mbShowPauseLogo = false;
850 // create a new temporary AnimationSlideController
851 mpSlideController->pushForPreview();
852 // Reference< XDrawPagesSupplier > xDrawPages( mpDoc->getUnoModel(), UNO_QUERY_THROW );
853 // Reference< XIndexAccess > xSlides( xDrawPages->getDrawPages(), UNO_QUERY_THROW );
854 // mpSlideController = std::make_shared<AnimationSlideController>( xSlides, AnimationSlideController::PREVIEW );
855 sal_Int32 nSlideNumber = 0;
856 Reference< XPropertySet > xSet( xDrawPage, UNO_QUERY_THROW );
857 xSet->getPropertyValue( u"Number"_ustr ) >>= nSlideNumber;
858 mpSlideController->insertSlideNumber( nSlideNumber-1 );
859 mpSlideController->setPreviewNode( xAnimationNode );
861 // prepare properties
862 sal_Int32 nPropertyCount = 1;
863 if( xAnimationNode.is() )
864 nPropertyCount++;
865 Sequence< beans::PropertyValue > aProperties(nPropertyCount);
866 auto pProperties = aProperties.getArray();
867 pProperties[0].Name = "AutomaticAdvancement";
868 pProperties[0].Value <<= 1.0; // one second timeout
870 if( xAnimationNode.is() )
872 pProperties[1].Name = "NoSlideTransitions";
873 pProperties[1].Value <<= true;
876 // start preview
877 startShowImpl( aProperties );
880 void SlideshowImpl::endInteractivePreview()
882 if (!mbInterActiveSetup)
883 // not in use, nothing to do
884 return;
886 // cleanup Show/View
889 if( mxView.is() )
890 mxShow->removeView( mxView );
892 Reference< XComponent > xComponent( mxShow, UNO_QUERY );
893 if( xComponent.is() )
894 xComponent->dispose();
896 if( mxView.is() )
897 mxView->dispose();
899 catch( Exception& )
901 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::stop()" );
903 mxShow.clear();
904 mxView.clear();
905 mxView = mxView2;
906 mxShow = mxShow2;
908 // restore SlideController
909 mpSlideController->popFromPreview();
911 // restore other settings and cleanup temporary incarnations
912 maPresSettings = maPresSettings2;
913 meAnimationMode = meAnimationMode2;
914 mxPreviewAnimationNode = mxPreviewAnimationNode2;
915 mxPreviewAnimationNode2.clear();
916 mxPreviewDrawPage = mxPreviewDrawPage2;
917 mxPreviewDrawPage2.clear();
919 // go back to slide shown before preview
920 gotoSlideIndex(mnSlideIndex);
922 // reset IASS mode flag
923 mbInterActiveSetup = false;
926 bool SlideshowImpl::startPreview(
927 const Reference< XDrawPage >& xDrawPage,
928 const Reference< XAnimationNode >& xAnimationNode,
929 vcl::Window * pParent )
931 bool bRet = false;
935 const Reference<lang::XServiceInfo> xServiceInfo( xDrawPage, UNO_QUERY );
936 if (xServiceInfo.is()) {
937 const Sequence<OUString> supportedServices(
938 xServiceInfo->getSupportedServiceNames() );
939 if (comphelper::findValue(supportedServices, "com.sun.star.drawing.MasterPage") != -1) {
940 OSL_FAIL("sd::SlideshowImpl::startPreview() "
941 "not allowed on master page!");
942 return false;
946 mxPreviewDrawPage = xDrawPage;
947 mxPreviewAnimationNode = xAnimationNode;
948 meAnimationMode = ANIMATIONMODE_PREVIEW;
950 maPresSettings.mbAll = false;
951 maPresSettings.mbEndless = false;
952 maPresSettings.mbCustomShow = false;
953 maPresSettings.mbManual = false;
954 maPresSettings.mbMouseVisible = false;
955 maPresSettings.mbMouseAsPen = false;
956 maPresSettings.mbLockedPages = false;
957 maPresSettings.mbAlwaysOnTop = false;
958 maPresSettings.mbFullScreen = false;
959 maPresSettings.mbAnimationAllowed = true;
960 maPresSettings.mnPauseTimeout = 0;
961 maPresSettings.mbShowPauseLogo = false;
963 rtl::Reference< SdXImpressDocument > xDrawPages( mpDoc->getUnoModel() );
964 Reference< XIndexAccess > xSlides( xDrawPages->getDrawPages(), UNO_QUERY_THROW );
965 mpSlideController = std::make_shared<AnimationSlideController>( xSlides, AnimationSlideController::PREVIEW );
967 sal_Int32 nSlideNumber = 0;
968 Reference< XPropertySet > xSet( mxPreviewDrawPage, UNO_QUERY_THROW );
969 xSet->getPropertyValue( u"Number"_ustr ) >>= nSlideNumber;
970 mpSlideController->insertSlideNumber( nSlideNumber-1 );
971 mpSlideController->setPreviewNode( xAnimationNode );
973 mpShowWindow = VclPtr<ShowWindow>::Create( this, ((pParent == nullptr) && mpViewShell) ? mpParentWindow.get() : pParent );
974 if( mpViewShell )
976 mpViewShell->SetActiveWindow( mpShowWindow );
977 mpShowWindow->SetViewShell (mpViewShell);
978 mpViewShell->ShowUIControls (false);
981 if( mpView )
983 mpView->AddDeviceToPaintView( *mpShowWindow->GetOutDev(), nullptr );
984 mpView->SetAnimationPause( true );
987 // call resize handler
988 if( pParent )
990 maPresSize = pParent->GetSizePixel();
992 else if( mpViewShell )
994 ::tools::Rectangle aContentRect (mpViewShell->GetViewShellBase().getClientRectangle());
995 if (AllSettings::GetLayoutRTL())
997 aContentRect.SetLeft( aContentRect.Right() );
998 aContentRect.AdjustRight(aContentRect.Right() );
1000 maPresSize = aContentRect.GetSize();
1001 mpShowWindow->SetPosPixel( aContentRect.TopLeft() );
1003 else
1005 OSL_FAIL("sd::SlideshowImpl::startPreview(), I need either a parent window or a viewshell!");
1007 resize( maPresSize );
1009 sal_Int32 nPropertyCount = 1;
1010 if( mxPreviewAnimationNode.is() )
1011 nPropertyCount++;
1013 Sequence< beans::PropertyValue > aProperties(nPropertyCount);
1014 auto pProperties = aProperties.getArray();
1015 pProperties[0].Name = "AutomaticAdvancement";
1016 pProperties[0].Value <<= 1.0; // one second timeout
1018 if( mxPreviewAnimationNode.is() )
1020 pProperties[1].Name = "NoSlideTransitions";
1021 pProperties[1].Value <<= true;
1024 bRet = startShowImpl( aProperties );
1026 if( mpShowWindow != nullptr && meAnimationMode == ANIMATIONMODE_PREVIEW )
1027 mpShowWindow->SetPreviewMode();
1030 catch( Exception& )
1032 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::startPreview()" );
1033 bRet = false;
1036 return bRet;
1039 bool SlideshowImpl::startShow( PresentationSettingsEx const * pPresSettings )
1041 const rtl::Reference<SlideshowImpl> xKeepAlive(this);
1043 DBG_ASSERT( !mxShow.is(), "sd::SlideshowImpl::startShow(), called twice!" );
1044 if( mxShow.is() )
1045 return true;
1046 DBG_ASSERT( mpParentWindow!=nullptr, "sd::SlideshowImpl::startShow() called without parent window" );
1047 if (mpParentWindow == nullptr)
1048 return false;
1050 // Autoplay (pps/ppsx)
1051 if (mpViewShell->GetDoc()->GetStartWithPresentation())
1053 mpViewShell->GetDoc()->SetExitAfterPresenting(true);
1056 bool bRet = false;
1060 if( pPresSettings )
1062 maPresSettings = *pPresSettings;
1063 mbRehearseTimings = pPresSettings->mbRehearseTimings;
1066 OUString aPresSlide( maPresSettings.maPresPage );
1067 SdPage* pStartPage = mpViewShell->GetActualPage();
1068 bool bStartWithActualSlide = pStartPage;
1070 // times should be measured?
1071 if( mbRehearseTimings )
1073 maPresSettings.mbEndless = false;
1074 maPresSettings.mbManual = true;
1075 maPresSettings.mbMouseVisible = true;
1076 maPresSettings.mbMouseAsPen = false;
1077 maPresSettings.mnPauseTimeout = 0;
1078 maPresSettings.mbShowPauseLogo = false;
1081 if( pStartPage )
1083 if( pStartPage->GetPageKind() == PageKind::Notes )
1085 // we are in notes page mode, so get
1086 // the corresponding draw page
1087 const sal_uInt16 nNotePgNum = pStartPage->GetPageNum();
1088 assert(nNotePgNum >= 2);
1089 const sal_uInt16 nPgNum = ( nNotePgNum - 2 ) >> 1;
1090 pStartPage = mpDoc->GetSdPage( nPgNum, PageKind::Standard );
1094 if( bStartWithActualSlide )
1096 if ( aPresSlide.isEmpty())
1098 // no preset slide yet, so pick current on one
1099 aPresSlide = pStartPage->GetName();
1100 // if the starting slide is hidden, we can't set slide controller to ALL mode
1101 maPresSettings.mbAll = !pStartPage->IsExcluded();
1104 if( meAnimationMode != ANIMATIONMODE_SHOW )
1106 if( pStartPage->GetPageKind() == PageKind::Standard )
1108 maPresSettings.mbAll = false;
1113 // build page list
1114 createSlideList( maPresSettings.mbAll, aPresSlide );
1116 // remember Slide number from where the show was started
1117 if( pStartPage )
1118 mnRestoreSlide = ( pStartPage->GetPageNum() - 1 ) / 2;
1120 if( mpSlideController->hasSlides() )
1122 // hide child windows
1123 hideChildWindows();
1125 mpShowWindow = VclPtr<ShowWindow>::Create( this, mpParentWindow );
1126 mpShowWindow->SetMouseAutoHide( !maPresSettings.mbMouseVisible );
1127 mpViewShell->SetActiveWindow( mpShowWindow );
1128 mpShowWindow->SetViewShell (mpViewShell);
1129 mpViewShell->GetViewShellBase().ShowUIControls (false);
1130 // Hide the side panes for in-place presentations.
1131 if ( ! maPresSettings.mbFullScreen)
1132 mpPaneHider.reset(new PaneHider(*mpViewShell,this));
1134 // these Slots are forbidden in other views for this document
1135 if( mpDocSh && pPresSettings && !pPresSettings->mbInteractive) // IASS
1137 mpDocSh->SetSlotFilter( true, pAllowed );
1138 mpDocSh->ApplySlotFilter();
1141 Help::DisableContextHelp();
1142 Help::DisableExtHelp();
1144 if( maPresSettings.mbFullScreen )
1146 #if HAVE_FEATURE_SCRIPTING
1147 // disable basic ide error handling
1148 maStarBASICGlobalErrorHdl = StarBASIC::GetGlobalErrorHdl();
1149 StarBASIC::SetGlobalErrorHdl( Link<StarBASIC*,bool>() );
1150 #endif
1153 // call resize handler
1154 maPresSize = mpParentWindow->GetSizePixel();
1155 if (!maPresSettings.mbFullScreen)
1157 const ::tools::Rectangle& aClientRect = mpViewShell->GetViewShellBase().getClientRectangle();
1158 maPresSize = aClientRect.GetSize();
1159 mpShowWindow->SetPosPixel( aClientRect.TopLeft() );
1160 resize( maPresSize );
1163 // #i41824#
1164 // Note: In FullScreen Mode the OS (window manager) sends a resize to
1165 // the WorkWindow once it actually resized it to full size. The
1166 // WorkWindow propagates the resize to the DrawViewShell which calls
1167 // resize() at the SlideShow (this). Calling resize here results in a
1168 // temporary display of a black window in the window's default size
1170 if( mpView )
1172 mpView->AddDeviceToPaintView( *mpShowWindow->GetOutDev(), nullptr );
1173 mpView->SetAnimationPause( true );
1176 SfxBindings* pBindings = getBindings();
1177 if( pBindings )
1179 pBindings->Invalidate( SID_PRESENTATION );
1180 pBindings->Invalidate( SID_REHEARSE_TIMINGS );
1183 // Defer the sd::ShowWindow's GrabFocus to SlideShow::activate. so that the accessible event can be fired correctly.
1184 //mpShowWindow->GrabFocus();
1186 std::vector<beans::PropertyValue> aProperties;
1187 aProperties.reserve( 4 );
1189 aProperties.emplace_back( "AdvanceOnClick" ,
1190 -1, Any( !maPresSettings.mbLockedPages ),
1191 beans::PropertyState_DIRECT_VALUE );
1193 aProperties.emplace_back( "ImageAnimationsAllowed" ,
1194 -1, Any( maPresSettings.mbAnimationAllowed ),
1195 beans::PropertyState_DIRECT_VALUE );
1197 const bool bZOrderEnabled(
1198 SdModule::get()->GetSdOptions( mpDoc->GetDocumentType() )->IsSlideshowRespectZOrder() );
1199 aProperties.emplace_back( "DisableAnimationZOrder" ,
1200 -1, Any( !bZOrderEnabled ),
1201 beans::PropertyState_DIRECT_VALUE );
1203 aProperties.emplace_back( "ForceManualAdvance" ,
1204 -1, Any( maPresSettings.mbManual ),
1205 beans::PropertyState_DIRECT_VALUE );
1207 if( mbUsePen )
1209 aProperties.emplace_back( "UserPaintColor" ,
1210 // User paint color is black by default.
1211 -1, Any( mnUserPaintColor ),
1212 beans::PropertyState_DIRECT_VALUE );
1214 aProperties.emplace_back( "UserPaintStrokeWidth" ,
1215 // User paint color is black by default.
1216 -1, Any( mdUserPaintStrokeWidth ),
1217 beans::PropertyState_DIRECT_VALUE );
1220 if (mbRehearseTimings) {
1221 aProperties.emplace_back( "RehearseTimings" ,
1222 -1, Any(true), beans::PropertyState_DIRECT_VALUE );
1225 bRet = startShowImpl( Sequence<beans::PropertyValue>(
1226 aProperties.data(), aProperties.size() ) );
1230 setActiveXToolbarsVisible( false );
1232 catch (const Exception&)
1234 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::startShow()" );
1235 bRet = false;
1238 return bRet;
1241 bool SlideshowImpl::startShowImpl( const Sequence< beans::PropertyValue >& aProperties )
1245 mxShow.set( createSlideShow(), UNO_SET_THROW );
1247 mxView = new SlideShowView(
1248 *mpShowWindow,
1249 mpDoc,
1250 meAnimationMode,
1251 this,
1252 maPresSettings.mbFullScreen);
1254 // try add wait symbol to properties:
1255 const Reference<rendering::XSpriteCanvas> xSpriteCanvas(
1256 mxView->getCanvas() );
1257 if (xSpriteCanvas.is())
1259 BitmapEx waitSymbolBitmap(BMP_WAIT_ICON);
1260 const Reference<rendering::XBitmap> xBitmap(
1261 vcl::unotools::xBitmapFromBitmapEx( waitSymbolBitmap ) );
1262 if (xBitmap.is())
1264 mxShow->setProperty(
1265 beans::PropertyValue( u"WaitSymbolBitmap"_ustr ,
1267 Any( xBitmap ),
1268 beans::PropertyState_DIRECT_VALUE ) );
1271 BitmapEx pointerSymbolBitmap(BMP_POINTER_ICON);
1272 const Reference<rendering::XBitmap> xPointerBitmap(
1273 vcl::unotools::xBitmapFromBitmapEx( pointerSymbolBitmap ) );
1274 if (xPointerBitmap.is())
1276 mxShow->setProperty(
1277 beans::PropertyValue( u"PointerSymbolBitmap"_ustr ,
1279 Any( xPointerBitmap ),
1280 beans::PropertyState_DIRECT_VALUE ) );
1282 if (officecfg::Office::Impress::Misc::Start::ShowNavigationPanel::get())
1284 NavbarButtonSize btnScale = static_cast<NavbarButtonSize>(officecfg::Office::Impress::Layout::Display::NavigationBtnScale::get());
1285 OUString prevSlidePath = u""_ustr;
1286 OUString nextSlidePath = u""_ustr;
1287 OUString menuPath = u""_ustr;
1288 switch (btnScale)
1290 case NavbarButtonSize::Large:
1292 prevSlidePath = BMP_PREV_SLIDE_LARGE;
1293 nextSlidePath = BMP_NEXT_SLIDE_LARGE;
1294 menuPath = BMP_MENU_SLIDE_LARGE;
1295 break;
1297 case NavbarButtonSize::XLarge:
1299 prevSlidePath = BMP_PREV_SLIDE_EXTRALARGE;
1300 nextSlidePath = BMP_NEXT_SLIDE_EXTRALARGE;
1301 menuPath = BMP_MENU_SLIDE_EXTRALARGE;
1302 break;
1304 case NavbarButtonSize::Auto:
1305 case NavbarButtonSize::Small:
1306 default:
1308 prevSlidePath = BMP_PREV_SLIDE_SMALL;
1309 nextSlidePath = BMP_NEXT_SLIDE_SMALL;
1310 menuPath = BMP_MENU_SLIDE_SMALL;
1311 break;
1314 BitmapEx prevSlideBm(prevSlidePath);
1315 const Reference<rendering::XBitmap> xPrevSBitmap(
1316 vcl::unotools::xBitmapFromBitmapEx(prevSlideBm));
1317 if (xPrevSBitmap.is())
1319 mxShow->setProperty(beans::PropertyValue(u"NavigationSlidePrev"_ustr, -1,
1320 Any(xPrevSBitmap),
1321 beans::PropertyState_DIRECT_VALUE));
1323 BitmapEx menuSlideBm(menuPath);
1324 const Reference<rendering::XBitmap> xMenuSBitmap(
1325 vcl::unotools::xBitmapFromBitmapEx(menuSlideBm));
1326 if (xMenuSBitmap.is())
1328 mxShow->setProperty(beans::PropertyValue(u"NavigationSlideMenu"_ustr, -1,
1329 Any(xMenuSBitmap),
1330 beans::PropertyState_DIRECT_VALUE));
1332 BitmapEx nextSlideBm(nextSlidePath);
1333 const Reference<rendering::XBitmap> xNextSBitmap(
1334 vcl::unotools::xBitmapFromBitmapEx(nextSlideBm));
1335 if (xNextSBitmap.is())
1337 mxShow->setProperty(beans::PropertyValue(u"NavigationSlideNext"_ustr, -1,
1338 Any(xNextSBitmap),
1339 beans::PropertyState_DIRECT_VALUE));
1344 for( const auto& rProp : aProperties )
1345 mxShow->setProperty( rProp );
1347 mxShow->addView( mxView );
1349 mxListenerProxy.set( new SlideShowListenerProxy( this, mxShow ) );
1350 mxListenerProxy->addAsSlideShowListener();
1352 // IASS: Do only startup the PresenterConsole if this is not
1353 // the SlideShow Preview mode (else would be double)
1354 if (!mbInterActiveSetup)
1356 // IASS: This is the central methodology to 'steer' the
1357 // PresenterConsole - in this case, to start it up and make
1358 // it visible (if activated)
1359 NotifyDocumentEvent(
1360 *mpDoc,
1361 u"OnStartPresentation"_ustr);
1364 displaySlideIndex( mpSlideController->getStartSlideIndex() );
1366 return true;
1368 catch( Exception& )
1370 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::startShowImpl()" );
1371 return false;
1375 /** called only by the slideshow view when the first paint event occurs.
1376 This actually starts the slideshow. */
1377 void SlideshowImpl::onFirstPaint()
1379 if( mpShowWindow )
1382 mpShowWindow->SetBackground( Wallpaper( COL_BLACK ) );
1383 mpShowWindow->Erase();
1384 mpShowWindow->SetBackground();
1388 SolarMutexGuard aSolarGuard;
1389 maUpdateTimer.SetTimeout( sal_uLong(100) );
1390 maUpdateTimer.Start();
1393 void SlideshowImpl::paint()
1395 if( mxView.is() ) try
1397 awt::PaintEvent aEvt;
1398 // aEvt.UpdateRect = TODO
1399 mxView->paint( aEvt );
1401 catch( Exception& )
1403 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::paint()" );
1407 void SAL_CALL SlideshowImpl::addSlideShowListener( const Reference< XSlideShowListener >& xListener )
1409 if( mxListenerProxy.is() )
1410 mxListenerProxy->addSlideShowListener( xListener );
1413 void SAL_CALL SlideshowImpl::removeSlideShowListener( const Reference< XSlideShowListener >& xListener )
1415 if( mxListenerProxy.is() )
1416 mxListenerProxy->removeSlideShowListener( xListener );
1419 void SlideshowImpl::slideEnded(const bool bReverse)
1421 if (bReverse)
1422 gotoPreviousSlide(true);
1423 else
1424 gotoNextSlide();
1427 bool SlideshowImpl::swipe(const CommandGestureSwipeData &rSwipeData)
1429 if (mbUsePen || mnContextMenuEvent)
1430 return false;
1431 double nVelocityX = rSwipeData.getVelocityX();
1432 // tdf#108475 make it swipe only if some reasonable movement was involved
1433 if (fabs(nVelocityX) < 50)
1434 return false;
1435 if (nVelocityX > 0)
1437 gotoPreviousSlide();
1439 else
1441 gotoNextEffect();
1443 //a swipe is followed by a mouse up, tell the view to ignore that mouse up as we've reacted
1444 //to the swipe instead
1445 mxView->ignoreNextMouseReleased();
1446 return true;
1449 bool SlideshowImpl::longpress(const CommandGestureLongPressData &rLongPressData)
1451 if (mnContextMenuEvent)
1452 return false;
1454 maPopupMousePos = Point(rLongPressData.getX(), rLongPressData.getY());
1455 mnContextMenuEvent = Application::PostUserEvent( LINK( this, SlideshowImpl, ContextMenuHdl ) );
1457 return true;
1460 void SlideshowImpl::removeShapeEvents()
1462 if( !(mxShow.is() && mxListenerProxy.is()) )
1463 return;
1467 for( const auto& rEntry : maShapeEventMap )
1469 mxListenerProxy->removeShapeEventListener( rEntry.first );
1470 mxShow->setShapeCursor( rEntry.first, awt::SystemPointer::ARROW );
1473 maShapeEventMap.clear();
1475 catch( Exception& )
1477 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::removeShapeEvents()" );
1481 void SlideshowImpl::registerShapeEvents(sal_Int32 nSlideNumber)
1483 if( nSlideNumber < 0 )
1484 return;
1488 Reference< XIndexAccess > xPages( mxModel->getDrawPages(), UNO_QUERY_THROW );
1490 Reference< XShapes > xDrawPage;
1491 xPages->getByIndex(nSlideNumber) >>= xDrawPage;
1493 if( xDrawPage.is() )
1495 Reference< XMasterPageTarget > xMasterPageTarget( xDrawPage, UNO_QUERY );
1496 if( xMasterPageTarget.is() )
1498 Reference< XShapes > xMasterPage = xMasterPageTarget->getMasterPage();
1499 if( xMasterPage.is() )
1500 registerShapeEvents( xMasterPage );
1502 registerShapeEvents( xDrawPage );
1505 catch( Exception& )
1507 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::registerShapeEvents()" );
1511 void SlideshowImpl::registerShapeEvents( Reference< XShapes > const & xShapes )
1515 const sal_Int32 nShapeCount = xShapes->getCount();
1516 sal_Int32 nShape;
1517 for( nShape = 0; nShape < nShapeCount; nShape++ )
1519 Reference< XShape > xShape;
1520 xShapes->getByIndex( nShape ) >>= xShape;
1522 if( xShape.is() && xShape->getShapeType() == "com.sun.star.drawing.GroupShape" )
1524 Reference< XShapes > xSubShapes( xShape, UNO_QUERY );
1525 if( xSubShapes.is() )
1526 registerShapeEvents( xSubShapes );
1529 Reference< XPropertySet > xSet( xShape, UNO_QUERY );
1530 if( !xSet.is() )
1531 continue;
1533 Reference< XPropertySetInfo > xSetInfo( xSet->getPropertySetInfo() );
1534 if( !xSetInfo.is() || !xSetInfo->hasPropertyByName( gsOnClick ) )
1535 continue;
1537 WrappedShapeEventImplPtr pEvent = std::make_shared<WrappedShapeEventImpl>();
1538 xSet->getPropertyValue( gsOnClick ) >>= pEvent->meClickAction;
1540 switch( pEvent->meClickAction )
1542 case ClickAction_PREVPAGE:
1543 case ClickAction_NEXTPAGE:
1544 case ClickAction_FIRSTPAGE:
1545 case ClickAction_LASTPAGE:
1546 case ClickAction_STOPPRESENTATION:
1547 break;
1548 case ClickAction_BOOKMARK:
1549 if( xSetInfo->hasPropertyByName( gsBookmark ) )
1550 xSet->getPropertyValue( gsBookmark ) >>= pEvent->maStrBookmark;
1551 if( getSlideNumberForBookmark( pEvent->maStrBookmark ) == -1 )
1552 continue;
1553 break;
1554 case ClickAction_DOCUMENT:
1555 case ClickAction_SOUND:
1556 case ClickAction_PROGRAM:
1557 case ClickAction_MACRO:
1558 if( xSetInfo->hasPropertyByName( gsBookmark ) )
1559 xSet->getPropertyValue( gsBookmark ) >>= pEvent->maStrBookmark;
1560 break;
1561 case ClickAction_VERB:
1562 if( xSetInfo->hasPropertyByName( gsVerb ) )
1563 xSet->getPropertyValue( gsVerb ) >>= pEvent->mnVerb;
1564 break;
1565 default:
1566 continue; // skip all others
1569 maShapeEventMap[ xShape ] = std::move(pEvent);
1571 if( mxListenerProxy.is() )
1572 mxListenerProxy->addShapeEventListener( xShape );
1573 mxShow->setShapeCursor( xShape, awt::SystemPointer::REFHAND );
1576 catch( Exception& )
1578 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::registerShapeEvents()" );
1582 void SlideshowImpl::displayCurrentSlide (const bool bSkipAllMainSequenceEffects)
1584 stopSound();
1585 removeShapeEvents();
1587 if( mpSlideController && mxShow.is() )
1589 rtl::Reference< SdXImpressDocument > xDrawPages( mpDoc->getUnoModel() );
1590 mpSlideController->displayCurrentSlide( mxShow, xDrawPages, bSkipAllMainSequenceEffects );
1591 registerShapeEvents(mpSlideController->getCurrentSlideNumber());
1592 update();
1595 // send out page change event and notify to update all acc info for current page
1596 if (mpViewShell)
1598 sal_Int32 currentPageIndex = getCurrentSlideIndex();
1599 mpViewShell->fireSwitchCurrentPage(currentPageIndex);
1600 mpViewShell->NotifyAccUpdate();
1604 void SlideshowImpl::endPresentation()
1606 if( maPresSettings.mbMouseAsPen)
1608 rtl::Reference< SdXImpressDocument > xDocFactory(mpDoc->getUnoModel() );
1609 if( xDocFactory.is() )
1610 mxShow->registerUserPaintPolygons(xDocFactory);
1613 if( !mnEndShowEvent )
1614 mnEndShowEvent = Application::PostUserEvent( LINK(this, SlideshowImpl, endPresentationHdl) );
1617 IMPL_LINK_NOARG(SlideshowImpl, endPresentationHdl, void*, void)
1619 mnEndShowEvent = nullptr;
1621 stopSound();
1623 if( mxPresentation.is() )
1624 mxPresentation->end();
1627 void SAL_CALL SlideshowImpl::pause()
1629 SolarMutexGuard aSolarGuard;
1631 if( mbIsPaused )
1632 return;
1636 mbIsPaused = true;
1637 if( mxShow.is() )
1639 mxShow->pause(true);
1641 if( mxListenerProxy.is() )
1642 mxListenerProxy->paused();
1645 catch( Exception& )
1647 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::pause()" );
1651 void SAL_CALL SlideshowImpl::resume()
1653 SolarMutexGuard aSolarGuard;
1655 if( mbIsPaused ) try
1657 if( mpShowWindow->GetShowWindowMode() == SHOWWINDOWMODE_BLANK || mpShowWindow->GetShowWindowMode() == SHOWWINDOWMODE_END )
1659 mpShowWindow->RestartShow();
1661 else
1663 mbIsPaused = false;
1664 if( mxShow.is() )
1666 mxShow->pause(false);
1667 update();
1669 if( mxListenerProxy.is() )
1670 mxListenerProxy->resumed();
1674 catch( Exception& )
1676 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::resume()" );
1678 #ifdef ENABLE_SDREMOTE
1679 RemoteServer::presentationStarted( this );
1680 #endif
1683 sal_Bool SAL_CALL SlideshowImpl::isPaused()
1685 SolarMutexGuard aSolarGuard;
1686 return mbIsPaused;
1689 void SAL_CALL SlideshowImpl::blankScreen( sal_Int32 nColor )
1691 SolarMutexGuard aSolarGuard;
1693 if( mpShowWindow && mpSlideController )
1695 if( mpShowWindow->SetBlankMode( mpSlideController->getCurrentSlideIndex(), Color(ColorTransparency, nColor) ) )
1697 pause();
1702 // XShapeEventListener
1704 void SlideshowImpl::click( const Reference< XShape >& xShape )
1706 SolarMutexGuard aSolarGuard;
1708 WrappedShapeEventImplPtr pEvent = maShapeEventMap[xShape];
1709 if( !pEvent )
1710 return;
1712 switch( pEvent->meClickAction )
1714 case ClickAction_PREVPAGE: gotoPreviousSlide(); break;
1715 case ClickAction_NEXTPAGE: gotoNextSlide(); break;
1716 case ClickAction_FIRSTPAGE: gotoFirstSlide(); break;
1717 case ClickAction_LASTPAGE: gotoLastSlide(); break;
1718 case ClickAction_STOPPRESENTATION: endPresentation(); break;
1719 case ClickAction_BOOKMARK:
1721 gotoBookmark( pEvent->maStrBookmark );
1723 break;
1724 case ClickAction_SOUND:
1726 #if HAVE_FEATURE_AVMEDIA
1729 mxPlayer.set(avmedia::MediaWindow::createPlayer(pEvent->maStrBookmark, u""_ustr/*TODO?*/), uno::UNO_SET_THROW );
1730 mxPlayer->start();
1732 catch( uno::Exception& )
1734 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::click()" );
1736 #endif
1738 break;
1740 case ClickAction_DOCUMENT:
1742 OUString aBookmark( pEvent->maStrBookmark );
1744 sal_Int32 nPos = aBookmark.indexOf( '#' );
1745 if( nPos >= 0 )
1747 OUString aURL( aBookmark.copy( 0, nPos+1 ) );
1748 OUString aName( aBookmark.copy( nPos+1 ) );
1749 aURL += getUiNameFromPageApiNameImpl( aName );
1750 aBookmark = aURL;
1753 mpDocSh->OpenBookmark( aBookmark );
1755 break;
1757 case ClickAction_PROGRAM:
1759 INetURLObject aURL(
1760 ::URIHelper::SmartRel2Abs(
1761 INetURLObject(mpDocSh->GetMedium()->GetBaseURL()),
1762 pEvent->maStrBookmark, ::URIHelper::GetMaybeFileHdl(), true,
1763 false, INetURLObject::EncodeMechanism::WasEncoded,
1764 INetURLObject::DecodeMechanism::Unambiguous ) );
1766 if( INetProtocol::File == aURL.GetProtocol() )
1768 SfxStringItem aUrl( SID_FILE_NAME, aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
1769 SfxBoolItem aBrowsing( SID_BROWSE, true );
1771 if (SfxViewFrame* pViewFrm = SfxViewFrame::Current())
1773 SfxUnoFrameItem aDocFrame(SID_FILLFRAME, pViewFrm->GetFrame().GetFrameInterface());
1774 pViewFrm->GetDispatcher()->ExecuteList( SID_OPENDOC,
1775 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD,
1776 { &aUrl, &aBrowsing }, { &aDocFrame } );
1780 break;
1782 #if HAVE_FEATURE_SCRIPTING
1783 case presentation::ClickAction_MACRO:
1785 const OUString aMacro( pEvent->maStrBookmark );
1787 if ( SfxApplication::IsXScriptURL( aMacro ) )
1789 Any aRet;
1790 Sequence< sal_Int16 > aOutArgsIndex;
1791 Sequence< Any > aOutArgs;
1792 Sequence< Any >* pInArgs = new Sequence< Any >(0);
1793 mpDocSh->CallXScript( aMacro, *pInArgs, aRet, aOutArgsIndex, aOutArgs);
1795 else
1797 // aMacro has the following syntax:
1798 // "Macroname.Modulname.Libname.Documentname" or
1799 // "Macroname.Modulname.Libname.Applicationname"
1800 sal_Int32 nIdx{ 0 };
1801 const std::u16string_view aMacroName = o3tl::getToken(aMacro, 0, '.', nIdx);
1802 const std::u16string_view aModulName = o3tl::getToken(aMacro, 0, '.', nIdx);
1804 // todo: is the limitation still given that only
1805 // Modulname+Macroname can be used here?
1806 OUString aExecMacro = OUString::Concat(aModulName) + "." + aMacroName;
1807 mpDocSh->GetBasic()->Call(aExecMacro);
1810 break;
1811 #endif
1813 case ClickAction_VERB:
1815 // todo, better do it async?
1816 SdrObject* pObj = SdrObject::getSdrObjectFromXShape(xShape);
1817 SdrOle2Obj* pOleObject = dynamic_cast< SdrOle2Obj* >(pObj);
1818 if (pOleObject && mpViewShell )
1819 mpViewShell->ActivateObject(pOleObject, pEvent->mnVerb);
1821 break;
1822 default:
1823 break;
1827 sal_Int32 SlideshowImpl::getSlideNumberForBookmark( const OUString& rStrBookmark )
1829 bool bIsMasterPage;
1830 OUString aBookmark = getUiNameFromPageApiNameImpl( rStrBookmark );
1831 sal_uInt16 nPgNum = mpDoc->GetPageByName( aBookmark, bIsMasterPage );
1833 if( nPgNum == SDRPAGE_NOTFOUND )
1835 // Is the bookmark an object?
1836 SdrObject* pObj = mpDoc->GetObj( aBookmark );
1838 if( pObj )
1840 nPgNum = pObj->getSdrPageFromSdrObject()->GetPageNum();
1841 bIsMasterPage = pObj->getSdrPageFromSdrObject()->IsMasterPage();
1845 if( (nPgNum == SDRPAGE_NOTFOUND) || bIsMasterPage || static_cast<SdPage*>(mpDoc->GetPage(nPgNum))->GetPageKind() != PageKind::Standard )
1846 return -1;
1848 return ( nPgNum - 1) >> 1;
1851 void SlideshowImpl::contextMenuShow(const css::awt::Point& point)
1853 maPopupMousePos = { point.X, point.Y };
1854 mnContextMenuEvent = Application::PostUserEvent(LINK(this, SlideshowImpl, ContextMenuHdl));
1857 void SlideshowImpl::hyperLinkClicked( OUString const& aHyperLink )
1859 OUString aBookmark( aHyperLink );
1861 sal_Int32 nPos = aBookmark.indexOf( '#' );
1862 if( nPos >= 0 )
1864 OUString aURL( aBookmark.copy( 0, nPos+1 ) );
1865 OUString aName( aBookmark.copy( nPos+1 ) );
1866 aURL += getUiNameFromPageApiNameImpl( aName );
1867 aBookmark = aURL;
1870 mpDocSh->OpenBookmark( aBookmark );
1873 void SlideshowImpl::displaySlideNumber( sal_Int32 nSlideNumber )
1875 if( mpSlideController )
1877 if( mpSlideController->jumpToSlideNumber( nSlideNumber ) )
1879 displayCurrentSlide();
1884 /** nSlideIndex == -1 displays current slide again */
1885 void SlideshowImpl::displaySlideIndex( sal_Int32 nSlideIndex )
1887 if( mpSlideController )
1889 if( (nSlideIndex == -1) || mpSlideController->jumpToSlideIndex( nSlideIndex ) )
1891 displayCurrentSlide();
1896 void SlideshowImpl::jumpToBookmark( const OUString& sBookmark )
1898 sal_Int32 nSlideNumber = getSlideNumberForBookmark( sBookmark );
1899 if( nSlideNumber != -1 )
1900 displaySlideNumber( nSlideNumber );
1903 sal_Int32 SlideshowImpl::getCurrentSlideNumber() const
1905 return mpSlideController ? mpSlideController->getCurrentSlideNumber() : -1;
1908 sal_Bool SAL_CALL SlideshowImpl::isEndless()
1910 SolarMutexGuard aSolarGuard;
1911 return maPresSettings.mbEndless;
1914 void SlideshowImpl::update()
1916 startUpdateTimer();
1919 void SlideshowImpl::startUpdateTimer()
1921 SolarMutexGuard aSolarGuard;
1922 maUpdateTimer.SetTimeout( 0 );
1923 maUpdateTimer.Start();
1926 /** this timer is called 20ms after a new slide was displayed.
1927 This is used to unfreeze user input that was disabled after
1928 slide change to skip input that was buffered during slide
1929 transition preparation */
1930 IMPL_LINK_NOARG(SlideshowImpl, ReadyForNextInputHdl, Timer *, void)
1932 mbInputFreeze = false;
1935 /** if I catch someone someday who calls this method by hand
1936 and not by using the timer, I will personally punish this
1937 person seriously, even if this person is me.
1939 IMPL_LINK_NOARG(SlideshowImpl, updateHdl, Timer *, void)
1941 updateSlideShow();
1944 void SlideshowImpl::updateSlideShow()
1946 // prevent me from deletion when recursing (App::EnableYieldMode does)
1947 const rtl::Reference<SlideshowImpl> xKeepAlive(this);
1949 Reference< XSlideShow > xShow( mxShow );
1950 if ( ! xShow.is())
1951 return;
1955 double fUpdate = 0.0;
1956 if( !xShow->update(fUpdate) )
1957 fUpdate = -1.0;
1959 if (mxShow.is() && (fUpdate >= 0.0))
1961 if (::basegfx::fTools::equalZero(fUpdate))
1963 // Make sure idle tasks don't starve when we don't have to wait.
1964 // Don't process any events generated after invoking the function.
1965 Application::Reschedule(/*bHandleAllCurrentEvents=*/true);
1967 else
1969 // Avoid busy loop when the previous call to update()
1970 // returns a small positive number but not 0 (which is
1971 // handled above). Also, make sure that calls to update()
1972 // have a minimum frequency.
1973 // => Allow up to 60 frames per second. Call at least once
1974 // every 4 seconds.
1975 const static sal_Int32 nMaximumFrameCount (60);
1976 const static double nMinimumTimeout (1.0 / nMaximumFrameCount);
1977 const static double nMaximumTimeout (4.0);
1978 fUpdate = std::clamp(fUpdate, nMinimumTimeout, nMaximumTimeout);
1980 // Make sure that the maximum frame count has not been set
1981 // too high (only then conversion to milliseconds and long
1982 // integer may lead to zero value.)
1983 OSL_ASSERT(static_cast<sal_uLong>(fUpdate * 1000.0) > 0);
1986 // Use our high resolution timers for the asynchronous callback.
1987 maUpdateTimer.SetTimeout(static_cast<sal_uLong>(fUpdate * 1000.0));
1988 maUpdateTimer.Start();
1991 catch( Exception& )
1993 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::updateSlideShow()" );
1997 bool SlideshowImpl::keyInput(const KeyEvent& rKEvt)
1999 if( !mxShow.is() || mbInputFreeze )
2000 return false;
2002 bool bRet = true;
2006 const int nKeyCode = rKEvt.GetKeyCode().GetCode();
2007 switch( nKeyCode )
2009 case awt::Key::CONTEXTMENU:
2010 if( !mnContextMenuEvent )
2012 if( mpShowWindow )
2013 maPopupMousePos = mpShowWindow->GetPointerState().maPos;
2014 mnContextMenuEvent = Application::PostUserEvent( LINK( this, SlideshowImpl, ContextMenuHdl ) );
2016 break;
2018 // cancel show
2019 case KEY_ESCAPE:
2020 case KEY_SUBTRACT:
2021 // in case the user cancels the presentation, switch to current slide
2022 // in edit mode
2023 if( mpSlideController && (ANIMATIONMODE_SHOW == meAnimationMode) )
2025 if( mpSlideController->getCurrentSlideNumber() != -1 )
2026 mnRestoreSlide = mpSlideController->getCurrentSlideNumber();
2028 endPresentation();
2029 break;
2031 // advance show
2032 case KEY_PAGEDOWN:
2033 if(rKEvt.GetKeyCode().IsMod2())
2035 gotoNextSlide();
2036 break;
2038 [[fallthrough]];
2039 case KEY_SPACE:
2040 case KEY_RIGHT:
2041 case KEY_DOWN:
2042 case KEY_XF86FORWARD:
2043 gotoNextEffect();
2044 break;
2046 case KEY_RETURN:
2048 if( !maCharBuffer.isEmpty() )
2050 if( mpSlideController )
2052 if( mpSlideController->jumpToSlideNumber( maCharBuffer.toInt32() - 1 ) )
2053 displayCurrentSlide();
2055 maCharBuffer.clear();
2057 else
2059 gotoNextEffect();
2062 break;
2064 // numeric: add to buffer
2065 case KEY_0:
2066 case KEY_1:
2067 case KEY_2:
2068 case KEY_3:
2069 case KEY_4:
2070 case KEY_5:
2071 case KEY_6:
2072 case KEY_7:
2073 case KEY_8:
2074 case KEY_9:
2075 maCharBuffer += OUStringChar( rKEvt.GetCharCode() );
2076 break;
2078 case KEY_PAGEUP:
2079 if(rKEvt.GetKeyCode().IsMod2())
2081 gotoPreviousSlide();
2082 break;
2084 [[fallthrough]];
2085 case KEY_LEFT:
2086 case KEY_UP:
2087 case KEY_BACKSPACE:
2088 case KEY_XF86BACK:
2089 gotoPreviousEffect();
2090 break;
2092 case KEY_P:
2093 setUsePen( !mbUsePen );
2094 break;
2096 // tdf#149351 Ctrl+A disables pointer as pen mode
2097 case KEY_A:
2098 if(rKEvt.GetKeyCode().IsMod1())
2100 setUsePen( false );
2101 break;
2103 break;
2105 case KEY_E:
2106 setEraseAllInk( true );
2107 updateSlideShow();
2108 break;
2110 case KEY_HOME:
2111 gotoFirstSlide();
2112 break;
2114 case KEY_END:
2115 gotoLastSlide();
2116 break;
2118 case KEY_B:
2119 case KEY_W:
2120 case KEY_POINT:
2121 case KEY_COMMA:
2123 blankScreen( ((nKeyCode == KEY_W ) || (nKeyCode == KEY_COMMA)) ? 0x00ffffff : 0x00000000 );
2125 break;
2127 default:
2128 bRet = false;
2129 break;
2132 catch( Exception& )
2134 bRet = false;
2135 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::keyInput()" );
2138 return bRet;
2141 IMPL_LINK( SlideshowImpl, EventListenerHdl, VclSimpleEvent&, rSimpleEvent, void )
2143 if( !mxShow.is() || mbInputFreeze )
2144 return;
2146 if( !((rSimpleEvent.GetId() == VclEventId::WindowCommand) && static_cast<VclWindowEvent*>(&rSimpleEvent)->GetData()) )
2147 return;
2149 const CommandEvent& rEvent = *static_cast<const CommandEvent*>(static_cast<VclWindowEvent*>(&rSimpleEvent)->GetData());
2151 if( rEvent.GetCommand() != CommandEventId::Media )
2152 return;
2154 CommandMediaData* pMediaData = rEvent.GetMediaData();
2155 pMediaData->SetPassThroughToOS(false);
2156 switch (pMediaData->GetMediaId())
2158 #if defined( MACOSX )
2159 case MediaCommand::Menu:
2160 if( !mnContextMenuEvent )
2162 if( mpShowWindow )
2163 maPopupMousePos = mpShowWindow->GetPointerState().maPos;
2164 mnContextMenuEvent = Application::PostUserEvent( LINK( this, SlideshowImpl, ContextMenuHdl ) );
2166 break;
2167 case MediaCommand::VolumeDown:
2168 gotoPreviousSlide();
2169 break;
2170 case MediaCommand::VolumeUp:
2171 gotoNextEffect();
2172 break;
2173 #endif
2174 case MediaCommand::NextTrack:
2175 gotoNextEffect();
2176 break;
2177 case MediaCommand::Pause:
2178 if( !mbIsPaused )
2179 blankScreen(0);
2180 break;
2181 case MediaCommand::Play:
2182 if( mbIsPaused )
2183 resume();
2184 break;
2186 case MediaCommand::PlayPause:
2187 if( mbIsPaused )
2188 resume();
2189 else
2190 blankScreen(0);
2191 break;
2192 case MediaCommand::PreviousTrack:
2193 gotoPreviousSlide();
2194 break;
2195 case MediaCommand::NextTrackHold:
2196 gotoLastSlide();
2197 break;
2199 case MediaCommand::Rewind:
2200 gotoFirstSlide();
2201 break;
2202 case MediaCommand::Stop:
2203 // in case the user cancels the presentation, switch to current slide
2204 // in edit mode
2205 if( mpSlideController && (ANIMATIONMODE_SHOW == meAnimationMode) )
2207 if( mpSlideController->getCurrentSlideNumber() != -1 )
2208 mnRestoreSlide = mpSlideController->getCurrentSlideNumber();
2210 endPresentation();
2211 break;
2212 default:
2213 pMediaData->SetPassThroughToOS(true);
2214 break;
2218 void SlideshowImpl::mouseButtonUp(const MouseEvent& rMEvt)
2220 if( rMEvt.IsRight() && !mnContextMenuEvent )
2222 maPopupMousePos = rMEvt.GetPosPixel();
2223 mnContextMenuEvent = Application::PostUserEvent( LINK( this, SlideshowImpl, ContextMenuHdl ) );
2227 IMPL_LINK_NOARG(SlideshowImpl, ContextMenuHdl, void*, void)
2229 mnContextMenuEvent = nullptr;
2231 if (mpSlideController == nullptr)
2232 return;
2234 mbWasPaused = mbIsPaused;
2235 if( !mbWasPaused )
2236 pause();
2238 std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(nullptr, u"modules/simpress/ui/slidecontextmenu.ui"_ustr));
2239 std::unique_ptr<weld::Menu> xMenu(xBuilder->weld_menu(u"menu"_ustr));
2240 OUString sNextImage(BMP_MENU_NEXT), sPrevImage(BMP_MENU_PREV);
2241 xMenu->insert(0, u"next"_ustr, SdResId(RID_SVXSTR_MENU_NEXT), &sNextImage, nullptr, nullptr, TRISTATE_INDET);
2242 xMenu->insert(1, u"prev"_ustr, SdResId(RID_SVXSTR_MENU_PREV), &sPrevImage, nullptr, nullptr, TRISTATE_INDET);
2244 // Adding button to display if in Pen mode
2245 xMenu->set_active(u"pen"_ustr, mbUsePen);
2247 const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode();
2248 xMenu->set_visible(u"next"_ustr, mpSlideController->getNextSlideIndex() != -1);
2249 xMenu->set_visible(u"prev"_ustr, (mpSlideController->getPreviousSlideIndex() != -1 ) || (eMode == SHOWWINDOWMODE_END) || (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK));
2250 xMenu->set_visible(u"edit"_ustr, mpViewShell->GetDoc()->GetStartWithPresentation() != 0);
2252 std::unique_ptr<weld::Menu> xPageMenu(xBuilder->weld_menu(u"gotomenu"_ustr));
2253 OUString sFirstImage(BMP_MENU_FIRST), sLastImage(BMP_MENU_LAST);
2254 xPageMenu->insert(0, u"first"_ustr, SdResId(RID_SVXSTR_MENU_FIRST), &sFirstImage, nullptr, nullptr, TRISTATE_INDET);
2255 xPageMenu->insert(1, u"last"_ustr, SdResId(RID_SVXSTR_MENU_LAST), &sLastImage, nullptr, nullptr, TRISTATE_INDET);
2257 // populate slide goto list
2258 const sal_Int32 nPageNumberCount = mpSlideController->getSlideNumberCount();
2259 if( nPageNumberCount <= 1 )
2261 xMenu->set_visible(u"goto"_ustr, false);
2263 else
2265 sal_Int32 nCurrentSlideNumber = mpSlideController->getCurrentSlideNumber();
2266 if( (eMode == SHOWWINDOWMODE_END) || (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) )
2267 nCurrentSlideNumber = -1;
2269 xPageMenu->set_visible(u"first"_ustr, mpSlideController->getSlideNumber(0) != nCurrentSlideNumber);
2270 xPageMenu->set_visible(u"last"_ustr, mpSlideController->getSlideNumber(mpSlideController->getSlideIndexCount() - 1) != nCurrentSlideNumber);
2272 sal_Int32 nPageNumber;
2274 for( nPageNumber = 0; nPageNumber < nPageNumberCount; nPageNumber++ )
2276 if( mpSlideController->isVisibleSlideNumber( nPageNumber ) )
2278 SdPage* pPage = mpDoc->GetSdPage(static_cast<sal_uInt16>(nPageNumber), PageKind::Standard);
2279 if (pPage)
2281 OUString sId(OUString::number(CM_SLIDES + nPageNumber));
2282 xPageMenu->append_check(sId, pPage->GetName());
2283 if (nPageNumber == nCurrentSlideNumber)
2284 xPageMenu->set_active(sId, true);
2290 std::unique_ptr<weld::Menu> xBlankMenu(xBuilder->weld_menu(u"screenmenu"_ustr));
2292 if (mpShowWindow->GetShowWindowMode() == SHOWWINDOWMODE_BLANK)
2294 xBlankMenu->set_active((mpShowWindow->GetBlankColor() == COL_WHITE) ? "white" : "black", true);
2297 std::unique_ptr<weld::Menu> xWidthMenu(xBuilder->weld_menu(u"widthmenu"_ustr));
2299 // populate color width list
2300 sal_Int32 nIterator;
2301 double nWidth;
2303 nWidth = 4.0;
2304 for( nIterator = 1; nIterator < 6; nIterator++)
2306 switch(nIterator)
2308 case 1:
2309 nWidth = 4.0;
2310 break;
2311 case 2:
2312 nWidth = 100.0;
2313 break;
2314 case 3:
2315 nWidth = 150.0;
2316 break;
2317 case 4:
2318 nWidth = 200.0;
2319 break;
2320 case 5:
2321 nWidth = 400.0;
2322 break;
2323 default:
2324 break;
2327 if (nWidth == mdUserPaintStrokeWidth)
2328 xWidthMenu->set_active(OUString::number(nWidth), true);
2331 ::tools::Rectangle aRect(maPopupMousePos, Size(1,1));
2332 weld::Window* pParent = weld::GetPopupParent(*mpShowWindow, aRect);
2333 ContextMenuSelectHdl(xMenu->popup_at_rect(pParent, aRect));
2335 if( mxView.is() )
2336 mxView->ignoreNextMouseReleased();
2338 if( !mbWasPaused )
2339 resume();
2342 void SlideshowImpl::ContextMenuSelectHdl(std::u16string_view rMenuId)
2344 if (rMenuId == u"prev")
2346 gotoPreviousSlide();
2347 mbWasPaused = false;
2349 else if(rMenuId == u"next")
2351 gotoNextSlide();
2352 mbWasPaused = false;
2354 else if (rMenuId == u"first")
2356 gotoFirstSlide();
2357 mbWasPaused = false;
2359 else if (rMenuId == u"last")
2361 gotoLastSlide();
2362 mbWasPaused = false;
2364 else if (rMenuId == u"black" || rMenuId == u"white")
2366 const Color aBlankColor(rMenuId == u"white" ? COL_WHITE : COL_BLACK);
2367 if( mbWasPaused )
2369 if( mpShowWindow->GetShowWindowMode() == SHOWWINDOWMODE_BLANK )
2371 if( mpShowWindow->GetBlankColor() == aBlankColor )
2373 mbWasPaused = false;
2374 mpShowWindow->RestartShow();
2375 return;
2378 mpShowWindow->RestartShow();
2380 if( mpShowWindow->SetBlankMode( mpSlideController->getCurrentSlideIndex(), aBlankColor ) )
2382 pause();
2383 mbWasPaused = true;
2386 else if (rMenuId == u"color")
2388 //Open a color picker based on SvColorDialog
2389 ::Color aColor( ColorTransparency, mnUserPaintColor );
2390 SvColorDialog aColorDlg;
2391 aColorDlg.SetColor( aColor );
2393 if (aColorDlg.Execute(mpShowWindow->GetFrameWeld()))
2395 aColor = aColorDlg.GetColor();
2396 setPenColor(sal_Int32(aColor));
2398 mbWasPaused = false;
2400 else if (rMenuId == u"4")
2402 setPenWidth(4.0);
2403 mbWasPaused = false;
2405 else if (rMenuId == u"100")
2407 setPenWidth(100.0);
2408 mbWasPaused = false;
2410 else if (rMenuId == u"150")
2412 setPenWidth(150.0);
2413 mbWasPaused = false;
2415 else if (rMenuId == u"200")
2417 setPenWidth(200.0);
2418 mbWasPaused = false;
2420 else if (rMenuId == u"400")
2422 setPenWidth(400.0);
2423 mbWasPaused = false;
2425 else if (rMenuId == u"erase")
2427 setEraseAllInk(true);
2428 mbWasPaused = false;
2430 else if (rMenuId == u"pen")
2432 setUsePen(!mbUsePen);
2433 mbWasPaused = false;
2435 else if (rMenuId == u"edit")
2437 // When in autoplay mode (pps/ppsx), offer editing of the presentation
2438 // Turn autostart off, else Impress will close when exiting the Presentation
2439 mpViewShell->GetDoc()->SetExitAfterPresenting(false);
2440 if( mpSlideController && (ANIMATIONMODE_SHOW == meAnimationMode) )
2442 if( mpSlideController->getCurrentSlideNumber() != -1 )
2444 mnRestoreSlide = mpSlideController->getCurrentSlideNumber();
2447 endPresentation();
2449 else if (rMenuId == u"end")
2451 // in case the user cancels the presentation, switch to current slide
2452 // in edit mode
2453 if( mpSlideController && (ANIMATIONMODE_SHOW == meAnimationMode) )
2455 if( mpSlideController->getCurrentSlideNumber() != -1 )
2457 mnRestoreSlide = mpSlideController->getCurrentSlideNumber();
2460 endPresentation();
2462 else if (!rMenuId.empty())
2464 sal_Int32 nPageNumber = o3tl::toInt32(rMenuId) - CM_SLIDES;
2465 const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode();
2466 if( (eMode == SHOWWINDOWMODE_END) || (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) )
2468 mpShowWindow->RestartShow( nPageNumber );
2470 else if( nPageNumber != mpSlideController->getCurrentSlideNumber() )
2472 displaySlideNumber( nPageNumber );
2474 mbWasPaused = false;
2478 Reference< XSlideShow > SlideshowImpl::createSlideShow()
2480 Reference< XSlideShow > xShow;
2484 const Reference< uno::XComponentContext >& xContext =
2485 ::comphelper::getProcessComponentContext();
2487 xShow.set( presentation::SlideShow::create(xContext), UNO_SET_THROW );
2489 catch( uno::Exception& )
2491 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::createSlideShow()" );
2494 return xShow;
2497 void SlideshowImpl::createSlideList( bool bAll, std::u16string_view rPresSlide )
2499 const sal_uInt16 nSlideCount = mpDoc->GetSdPageCount( PageKind::Standard );
2501 if( !nSlideCount )
2502 return;
2504 SdCustomShow* pCustomShow;
2506 if( mpDoc->GetCustomShowList() && maPresSettings.mbCustomShow )
2507 pCustomShow = mpDoc->GetCustomShowList()->GetCurObject();
2508 else
2509 pCustomShow = nullptr;
2511 // create animation slide controller
2512 AnimationSlideController::Mode eMode =
2513 ( pCustomShow && !pCustomShow->PagesVector().empty() ) ? AnimationSlideController::CUSTOM :
2514 (bAll ? AnimationSlideController::ALL : AnimationSlideController::FROM);
2516 rtl::Reference< SdXImpressDocument > xDrawPages( mpDoc->getUnoModel() );
2517 Reference< XIndexAccess > xSlides( xDrawPages->getDrawPages(), UNO_QUERY_THROW );
2518 mpSlideController = std::make_shared<AnimationSlideController>( xSlides, eMode );
2520 if( eMode != AnimationSlideController::CUSTOM )
2522 sal_Int32 nFirstVisibleSlide = 0;
2524 // normal presentation
2525 if( !rPresSlide.empty() )
2527 sal_Int32 nSlide;
2528 bool bTakeNextAvailable = false;
2530 for( nSlide = 0, nFirstVisibleSlide = -1;
2531 ( nSlide < nSlideCount ) && ( -1 == nFirstVisibleSlide ); nSlide++ )
2533 SdPage* pTestSlide = mpDoc->GetSdPage( static_cast<sal_uInt16>(nSlide), PageKind::Standard );
2535 if( pTestSlide->GetName() == rPresSlide )
2537 if( pTestSlide->IsExcluded() )
2538 bTakeNextAvailable = true;
2539 else
2540 nFirstVisibleSlide = nSlide;
2542 else if( bTakeNextAvailable && !pTestSlide->IsExcluded() )
2543 nFirstVisibleSlide = nSlide;
2546 if( -1 == nFirstVisibleSlide )
2547 nFirstVisibleSlide = 0;
2550 for( sal_Int32 i = 0; i < nSlideCount; i++ )
2552 bool bVisible = ! mpDoc->GetSdPage( static_cast<sal_uInt16>(i), PageKind::Standard )->IsExcluded();
2553 if( bVisible || (eMode == AnimationSlideController::ALL) )
2554 mpSlideController->insertSlideNumber( i, bVisible );
2557 mpSlideController->setStartSlideNumber( nFirstVisibleSlide );
2559 else
2561 if( meAnimationMode != ANIMATIONMODE_SHOW && !rPresSlide.empty() )
2563 sal_Int32 nSlide;
2564 for( nSlide = 0; nSlide < nSlideCount; nSlide++ )
2565 if( rPresSlide == mpDoc->GetSdPage( static_cast<sal_uInt16>(nSlide), PageKind::Standard )->GetName() )
2566 break;
2568 if( nSlide < nSlideCount )
2569 mpSlideController->insertSlideNumber( static_cast<sal_uInt16>(nSlide) );
2572 for( const auto& rpPage : pCustomShow->PagesVector() )
2574 const sal_uInt16 nSdSlide = ( rpPage->GetPageNum() - 1 ) / 2;
2576 if( ! mpDoc->GetSdPage( nSdSlide, PageKind::Standard )->IsExcluded())
2577 mpSlideController->insertSlideNumber( nSdSlide );
2582 typedef sal_uInt16 (*FncGetChildWindowId)();
2584 const FncGetChildWindowId aShowChildren[] =
2586 &AnimationChildWindow::GetChildWindowId,
2587 &Svx3DChildWindow::GetChildWindowId,
2588 &SvxFontWorkChildWindow::GetChildWindowId,
2589 &SvxColorChildWindow::GetChildWindowId,
2590 &SvxSearchDialogWrapper::GetChildWindowId,
2591 &SvxBmpMaskChildWindow::GetChildWindowId,
2592 &SvxIMapDlgChildWindow::GetChildWindowId,
2593 &SvxHlinkDlgWrapper::GetChildWindowId,
2594 &SfxInfoBarContainerChild::GetChildWindowId
2597 void SlideshowImpl::hideChildWindows()
2599 mnChildMask = 0;
2601 if( ANIMATIONMODE_SHOW != meAnimationMode )
2602 return;
2604 SfxViewFrame* pViewFrame = getViewFrame();
2606 if( !pViewFrame )
2607 return;
2609 for( sal_uLong i = 0; i < SAL_N_ELEMENTS( aShowChildren ); i++ )
2611 const sal_uInt16 nId = ( *aShowChildren[ i ] )();
2613 if( pViewFrame->GetChildWindow( nId ) )
2615 pViewFrame->SetChildWindow( nId, false );
2616 mnChildMask |= ::tools::ULong(1) << i;
2621 void SlideshowImpl::showChildWindows()
2623 if( ANIMATIONMODE_SHOW == meAnimationMode )
2625 SfxViewFrame* pViewFrame = getViewFrame();
2626 if( pViewFrame )
2628 for( sal_uLong i = 0; i < SAL_N_ELEMENTS(aShowChildren); i++ )
2630 if( mnChildMask & ( ::tools::ULong(1) << i ) )
2631 pViewFrame->SetChildWindow( ( *aShowChildren[ i ] )(), true );
2637 SfxViewFrame* SlideshowImpl::getViewFrame() const
2639 return mpViewShell ? mpViewShell->GetViewFrame() : nullptr;
2642 SfxDispatcher* SlideshowImpl::getDispatcher() const
2644 return (mpViewShell && mpViewShell->GetViewFrame()) ? mpViewShell->GetViewFrame()->GetDispatcher() : nullptr;
2647 SfxBindings* SlideshowImpl::getBindings() const
2649 return (mpViewShell && mpViewShell->GetViewFrame()) ? &mpViewShell->GetViewFrame()->GetBindings() : nullptr;
2652 void SlideshowImpl::resize( const Size& rSize )
2654 maPresSize = rSize;
2656 if(mpShowWindow)
2658 mpShowWindow->SetSizePixel( maPresSize );
2659 mpShowWindow->Show();
2662 if( mxView.is() ) try
2664 awt::WindowEvent aEvt;
2665 mxView->windowResized(aEvt);
2667 catch( Exception& )
2669 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::resize()" );
2673 void SlideshowImpl::setActiveXToolbarsVisible( bool bVisible )
2675 // in case of ActiveX control the toolbars should not be visible if slide show runs in window mode
2676 // actually it runs always in window mode in case of ActiveX control
2677 if ( !(!maPresSettings.mbFullScreen && mpDocSh && mpDocSh->GetMedium()) )
2678 return;
2680 const SfxBoolItem* pItem = mpDocSh->GetMedium()->GetItemSet().GetItem(SID_VIEWONLY, false);
2681 if ( !(pItem && pItem->GetValue()) )
2682 return;
2684 // this is a plugin/activex mode, no toolbars should be visible during slide show
2685 // after the end of slide show they should be visible again
2686 SfxViewFrame* pViewFrame = getViewFrame();
2687 if( !pViewFrame )
2688 return;
2692 Reference< frame::XLayoutManager > xLayoutManager;
2693 Reference< beans::XPropertySet > xFrameProps( pViewFrame->GetFrame().GetFrameInterface(), UNO_QUERY_THROW );
2694 if ( ( xFrameProps->getPropertyValue( u"LayoutManager"_ustr )
2695 >>= xLayoutManager )
2696 && xLayoutManager.is() )
2698 xLayoutManager->setVisible( bVisible );
2701 catch( uno::Exception& )
2705 void SAL_CALL SlideshowImpl::activate()
2707 SolarMutexGuard aSolarGuard;
2709 maDeactivateTimer.Stop();
2711 if( mbActive || !mxShow.is() )
2712 return;
2714 mbActive = true;
2716 if( ANIMATIONMODE_SHOW == meAnimationMode )
2718 if( mbAutoSaveWasOn )
2719 setAutoSaveState( false );
2721 if( mpShowWindow )
2723 SfxViewFrame* pViewFrame = getViewFrame();
2724 SfxDispatcher* pDispatcher = pViewFrame ? pViewFrame->GetDispatcher() : nullptr;
2726 hideChildWindows();
2728 if( pDispatcher )
2730 // filter all forbidden slots
2731 pDispatcher->SetSlotFilter( SfxSlotFilterState::ENABLED, pAllowed );
2734 if( getBindings() )
2735 getBindings()->InvalidateAll(true);
2737 mpShowWindow->GrabFocus();
2741 resume();
2744 void SAL_CALL SlideshowImpl::deactivate()
2746 SolarMutexGuard aSolarGuard;
2748 if( mbActive && mxShow.is() )
2750 maDeactivateTimer.Start();
2754 IMPL_LINK_NOARG(SlideshowImpl, deactivateHdl, Timer *, void)
2756 if( !(mbActive && mxShow.is()) )
2757 return;
2759 mbActive = false;
2761 pause();
2763 if( ANIMATIONMODE_SHOW == meAnimationMode )
2765 if( mbAutoSaveWasOn )
2766 setAutoSaveState( true );
2768 if( mpShowWindow )
2770 showChildWindows();
2775 sal_Bool SAL_CALL SlideshowImpl::isActive()
2777 SolarMutexGuard aSolarGuard;
2778 return mbActive;
2781 void SlideshowImpl::setAutoSaveState( bool bOn)
2785 const uno::Reference<uno::XComponentContext>& xContext( ::comphelper::getProcessComponentContext() );
2787 uno::Reference< util::XURLTransformer > xParser(util::URLTransformer::create(xContext));
2788 util::URL aURL;
2789 aURL.Complete = "vnd.sun.star.autorecovery:/setAutoSaveState";
2790 xParser->parseStrict(aURL);
2792 Sequence< beans::PropertyValue > aArgs{ comphelper::makePropertyValue(u"AutoSaveState"_ustr, bOn) };
2794 uno::Reference< frame::XDispatch > xAutoSave = frame::theAutoRecovery::get(xContext);
2795 xAutoSave->dispatch(aURL, aArgs);
2797 catch( Exception& )
2799 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::setAutoSaveState()");
2803 Reference< XDrawPage > SAL_CALL SlideshowImpl::getCurrentSlide()
2805 SolarMutexGuard aSolarGuard;
2807 Reference< XDrawPage > xSlide;
2808 if( mxShow.is() && mpSlideController )
2810 sal_Int32 nSlide = getCurrentSlideNumber();
2811 if( (nSlide >= 0) && (nSlide < mpSlideController->getSlideNumberCount() ) )
2812 xSlide = mpSlideController->getSlideByNumber( nSlide );
2815 return xSlide;
2818 sal_Int32 SAL_CALL SlideshowImpl::getNextSlideIndex()
2820 SolarMutexGuard aSolarGuard;
2822 if( mxShow.is() )
2824 return mpSlideController->getNextSlideIndex();
2826 else
2828 return -1;
2832 sal_Int32 SAL_CALL SlideshowImpl::getCurrentSlideIndex()
2834 return mpSlideController ? mpSlideController->getCurrentSlideIndex() : -1;
2837 // css::presentation::XSlideShowController:
2839 ::sal_Int32 SAL_CALL SlideshowImpl::getSlideCount()
2841 return mpSlideController ? mpSlideController->getSlideIndexCount() : 0;
2844 Reference< XDrawPage > SAL_CALL SlideshowImpl::getSlideByIndex(::sal_Int32 Index)
2846 if ((mpSlideController == nullptr) || (Index < 0)
2847 || (Index >= mpSlideController->getSlideIndexCount()))
2848 throw IndexOutOfBoundsException();
2850 return mpSlideController->getSlideByNumber( mpSlideController->getSlideNumber( Index ) );
2853 sal_Bool SAL_CALL SlideshowImpl::getAlwaysOnTop()
2855 SolarMutexGuard aSolarGuard;
2856 return maPresSettings.mbAlwaysOnTop;
2859 void SAL_CALL SlideshowImpl::setAlwaysOnTop( sal_Bool bAlways )
2861 SolarMutexGuard aSolarGuard;
2862 if( maPresSettings.mbAlwaysOnTop != bool(bAlways) )
2864 maPresSettings.mbAlwaysOnTop = bAlways;
2865 // todo, can this be changed while running?
2869 sal_Bool SAL_CALL SlideshowImpl::isFullScreen()
2871 SolarMutexGuard aSolarGuard;
2872 return maPresSettings.mbFullScreen;
2875 sal_Bool SAL_CALL SlideshowImpl::getMouseVisible()
2877 SolarMutexGuard aSolarGuard;
2878 return maPresSettings.mbMouseVisible;
2881 void SAL_CALL SlideshowImpl::setMouseVisible( sal_Bool bVisible )
2883 SolarMutexGuard aSolarGuard;
2884 if( maPresSettings.mbMouseVisible != bool(bVisible) )
2886 maPresSettings.mbMouseVisible = bVisible;
2887 if( mpShowWindow )
2888 mpShowWindow->SetMouseAutoHide( !maPresSettings.mbMouseVisible );
2892 sal_Bool SAL_CALL SlideshowImpl::getUsePen()
2894 SolarMutexGuard aSolarGuard;
2895 return mbUsePen;
2898 void SAL_CALL SlideshowImpl::setUsePen( sal_Bool bMouseAsPen )
2900 SolarMutexGuard aSolarGuard;
2901 mbUsePen = bMouseAsPen;
2902 if( !mxShow.is() )
2903 return;
2907 // For Pencolor;
2908 beans::PropertyValue aPenProp;
2909 aPenProp.Name = "UserPaintColor";
2910 if( mbUsePen )
2911 aPenProp.Value <<= mnUserPaintColor;
2912 mxShow->setProperty( aPenProp );
2914 //for StrokeWidth :
2915 if( mbUsePen )
2917 beans::PropertyValue aPenPropWidth;
2918 aPenPropWidth.Name = "UserPaintStrokeWidth";
2919 aPenPropWidth.Value <<= mdUserPaintStrokeWidth;
2920 mxShow->setProperty( aPenPropWidth );
2922 // for Pen Mode
2923 beans::PropertyValue aPenPropSwitchPenMode;
2924 aPenPropSwitchPenMode.Name = "SwitchPenMode";
2925 aPenPropSwitchPenMode.Value <<= true;
2926 mxShow->setProperty( aPenPropSwitchPenMode );
2929 catch( Exception& )
2931 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::setUsePen()" );
2935 double SAL_CALL SlideshowImpl::getPenWidth()
2937 SolarMutexGuard aSolarGuard;
2938 return mdUserPaintStrokeWidth;
2941 void SAL_CALL SlideshowImpl::setPenWidth( double dStrokeWidth )
2943 SolarMutexGuard aSolarGuard;
2944 mdUserPaintStrokeWidth = dStrokeWidth;
2945 setUsePen( true ); // enable pen mode, update color and width
2948 sal_Int32 SAL_CALL SlideshowImpl::getPenColor()
2950 SolarMutexGuard aSolarGuard;
2951 return mnUserPaintColor;
2954 void SAL_CALL SlideshowImpl::setPenColor( sal_Int32 nColor )
2956 SolarMutexGuard aSolarGuard;
2957 mnUserPaintColor = nColor;
2958 setUsePen( true ); // enable pen mode, update color
2961 void SAL_CALL SlideshowImpl::setEraseAllInk(sal_Bool bEraseAllInk)
2963 if( !bEraseAllInk )
2964 return;
2966 SolarMutexGuard aSolarGuard;
2967 if( !mxShow.is() )
2968 return;
2972 beans::PropertyValue aPenPropEraseAllInk;
2973 aPenPropEraseAllInk.Name = "EraseAllInk";
2974 aPenPropEraseAllInk.Value <<= bEraseAllInk;
2975 mxShow->setProperty( aPenPropEraseAllInk );
2977 catch( Exception& )
2979 TOOLS_WARN_EXCEPTION( "sd.slideshow", "sd::SlideshowImpl::setEraseAllInk()" );
2983 // XSlideShowController Methods
2984 sal_Bool SAL_CALL SlideshowImpl::isRunning( )
2986 SolarMutexGuard aSolarGuard;
2987 return mxShow.is();
2990 void SAL_CALL SlideshowImpl::gotoNextEffect( )
2992 SolarMutexGuard aSolarGuard;
2994 if( !(mxShow.is() && mpSlideController && mpShowWindow) )
2995 return;
2997 if( mbIsPaused && mpShowWindow->GetShowWindowMode() != SHOWWINDOWMODE_END )
2998 resume();
3000 const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode();
3001 if( eMode == SHOWWINDOWMODE_END )
3003 endPresentation();
3005 else if( (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) )
3007 mpShowWindow->RestartShow();
3009 else
3011 mxShow->nextEffect();
3012 update();
3016 void SAL_CALL SlideshowImpl::gotoPreviousEffect( )
3018 SolarMutexGuard aSolarGuard;
3020 if( !(mxShow.is() && mpSlideController && mpShowWindow) )
3021 return;
3023 const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode();
3024 if( (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) || mbIsPaused )
3026 resume();
3028 else
3030 mxShow->previousEffect();
3031 update();
3035 void SAL_CALL SlideshowImpl::gotoFirstSlide( )
3037 SolarMutexGuard aSolarGuard;
3039 if( !(mpShowWindow && mpSlideController) )
3040 return;
3042 if( mbIsPaused )
3043 resume();
3045 if( mpShowWindow->GetShowWindowMode() == SHOWWINDOWMODE_END )
3047 if( mpSlideController->getSlideIndexCount() )
3048 mpShowWindow->RestartShow( 0);
3050 else
3052 displaySlideIndex( 0 );
3056 void SAL_CALL SlideshowImpl::gotoNextSlide( )
3058 SolarMutexGuard aSolarGuard;
3060 if( mbIsPaused )
3061 resume();
3063 const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode();
3064 if( (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) )
3066 mpShowWindow->RestartShow();
3068 else
3070 // if this is a show, ignore user inputs and
3071 // start 20ms timer to reenable inputs to filter
3072 // buffered inputs during slide transition
3073 if( meAnimationMode == ANIMATIONMODE_SHOW )
3075 mbInputFreeze = true;
3076 maInputFreezeTimer.Start();
3079 if( mpSlideController )
3081 if( mpSlideController->nextSlide() )
3083 displayCurrentSlide();
3085 else
3087 stopSound();
3089 if( meAnimationMode == ANIMATIONMODE_PREVIEW )
3091 endPresentation();
3093 else if( maPresSettings.mbEndless )
3095 if( maPresSettings.mnPauseTimeout )
3097 if( mpShowWindow )
3099 if ( maPresSettings.mbShowPauseLogo )
3101 Graphic aGraphic(SfxApplication::GetApplicationLogo(360));
3102 mpShowWindow->SetPauseMode( maPresSettings.mnPauseTimeout, &aGraphic );
3104 else
3105 mpShowWindow->SetPauseMode( maPresSettings.mnPauseTimeout );
3108 else
3110 displaySlideIndex( 0 );
3113 else
3115 if( mpShowWindow )
3117 mpShowWindow->SetEndMode();
3118 if (!mpViewShell->GetDoc()->GetStartWithPresentation())
3119 pause();
3127 void SAL_CALL SlideshowImpl::gotoPreviousSlide( )
3129 gotoPreviousSlide(false);
3132 void SlideshowImpl::gotoPreviousSlide (const bool bSkipAllMainSequenceEffects)
3134 SolarMutexGuard aSolarGuard;
3136 if( !(mxShow.is() && mpSlideController) )
3137 return;
3141 if( mbIsPaused )
3142 resume();
3144 const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode();
3145 if( eMode == SHOWWINDOWMODE_END )
3147 mpShowWindow->RestartShow( mpSlideController->getCurrentSlideIndex() );
3149 else if( (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) )
3151 mpShowWindow->RestartShow();
3153 else
3155 if( mpSlideController->previousSlide())
3156 displayCurrentSlide(bSkipAllMainSequenceEffects);
3157 else if (bSkipAllMainSequenceEffects)
3159 // We could not go to the previous slide (probably because
3160 // the current slide is already the first one). We still
3161 // have to call displayCurrentSlide because the calling
3162 // slideshow can not determine whether there is a previous
3163 // slide or not and has already prepared for a slide change.
3164 // This slide change has to be completed now, even when
3165 // changing to the same slide.
3166 // Note that in this special case we do NOT pass
3167 // bSkipAllMainSequenceEffects because we display the same
3168 // slide as before and do not want to show all its effects.
3169 displayCurrentSlide();
3173 catch( Exception& )
3175 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::gotoPreviousSlide()" );
3179 void SAL_CALL SlideshowImpl::gotoLastSlide()
3181 SolarMutexGuard aSolarGuard;
3183 if( !mpSlideController )
3184 return;
3186 if( mbIsPaused )
3187 resume();
3189 const sal_Int32 nLastSlideIndex = mpSlideController->getSlideIndexCount() - 1;
3190 if( nLastSlideIndex >= 0 )
3192 if( mpShowWindow->GetShowWindowMode() == SHOWWINDOWMODE_END )
3194 mpShowWindow->RestartShow( nLastSlideIndex );
3196 else
3198 displaySlideIndex( nLastSlideIndex );
3203 void SAL_CALL SlideshowImpl::gotoBookmark( const OUString& rBookmark )
3205 SolarMutexGuard aSolarGuard;
3207 if( mbIsPaused )
3208 resume();
3210 sal_Int32 nSlideNumber = getSlideNumberForBookmark( rBookmark );
3211 if( nSlideNumber != -1 )
3212 displaySlideNumber( nSlideNumber );
3215 void SAL_CALL SlideshowImpl::gotoSlide( const Reference< XDrawPage >& xSlide )
3217 SolarMutexGuard aSolarGuard;
3219 if( !(mpSlideController && xSlide.is()) )
3220 return;
3222 if( mbIsPaused )
3223 resume();
3225 const sal_Int32 nSlideCount = mpSlideController->getSlideNumberCount();
3226 for( sal_Int32 nSlide = 0; nSlide < nSlideCount; nSlide++ )
3228 if( mpSlideController->getSlideByNumber( nSlide ) == xSlide )
3230 displaySlideNumber( nSlide );
3235 void SAL_CALL SlideshowImpl::gotoSlideIndex( sal_Int32 nIndex )
3237 SolarMutexGuard aSolarGuard;
3239 if( mbIsPaused )
3240 resume();
3242 displaySlideIndex( nIndex );
3245 void SAL_CALL SlideshowImpl::stopSound( )
3247 SolarMutexGuard aSolarGuard;
3251 if( mxPlayer.is() )
3253 mxPlayer->stop();
3254 mxPlayer.clear();
3257 catch( Exception& )
3259 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::stopSound()" );
3263 // XIndexAccess
3265 ::sal_Int32 SAL_CALL SlideshowImpl::getCount( )
3267 return getSlideCount();
3270 css::uno::Any SAL_CALL SlideshowImpl::getByIndex( ::sal_Int32 Index )
3272 return Any( getSlideByIndex( Index ) );
3275 css::uno::Type SAL_CALL SlideshowImpl::getElementType( )
3277 return cppu::UnoType<XDrawPage>::get();
3280 sal_Bool SAL_CALL SlideshowImpl::hasElements( )
3282 return getSlideCount() != 0;
3285 namespace
3287 class AsyncUpdateSlideshow_Impl
3289 public:
3290 struct AsyncUpdateSlideshowData
3292 SlideshowImpl* pSlideshowImpl;
3293 uno::Reference< css::drawing::XDrawPage > XCurrentSlide;
3294 SdrHintKind eHintKind;
3297 static ImplSVEvent* AsyncUpdateSlideshow(
3298 SlideshowImpl* pSlideshowImpl,
3299 uno::Reference< css::drawing::XDrawPage >& rXCurrentSlide,
3300 SdrHintKind eHintKind)
3302 AsyncUpdateSlideshowData* pNew(new AsyncUpdateSlideshowData);
3303 pNew->pSlideshowImpl = pSlideshowImpl;
3304 pNew->XCurrentSlide = rXCurrentSlide;
3305 pNew->eHintKind = eHintKind;
3306 return Application::PostUserEvent(LINK(nullptr, AsyncUpdateSlideshow_Impl, Update), pNew);
3307 // coverity[leaked_storage] - pDisruptor takes care of its own destruction at idle time
3310 DECL_STATIC_LINK(AsyncUpdateSlideshow_Impl, Update, void*, void);
3313 IMPL_STATIC_LINK(AsyncUpdateSlideshow_Impl, Update, void*, pData, void)
3315 AsyncUpdateSlideshowData* pSlideData(static_cast<AsyncUpdateSlideshowData*>(pData));
3316 pSlideData->pSlideshowImpl->AsyncNotifyEvent(pSlideData->XCurrentSlide, pSlideData->eHintKind);
3317 delete pSlideData;
3321 void SlideshowImpl::AsyncNotifyEvent(
3322 const uno::Reference< css::drawing::XDrawPage >& rXCurrentSlide,
3323 const SdrHintKind eHintKind)
3325 switch (eHintKind)
3327 case SdrHintKind::ObjectInserted:
3329 mnEventObjectInserted = nullptr;
3331 // refresh single slide
3332 gotoSlide(rXCurrentSlide);
3333 break;
3335 case SdrHintKind::ObjectRemoved:
3337 mnEventObjectRemoved = nullptr;
3339 // refresh single slide
3340 gotoSlide(rXCurrentSlide);
3341 break;
3343 case SdrHintKind::ObjectChange:
3345 mnEventObjectChange = nullptr;
3347 // refresh single slide
3348 gotoSlide(rXCurrentSlide);
3349 break;
3351 case SdrHintKind::PageOrderChange:
3353 mnEventPageOrderChange = nullptr;
3355 // order of pages (object pages or master pages) changed (Insert/Remove/ChangePos)
3356 // rXCurrentSlide is the current slide before the change.
3357 rtl::Reference< SdXImpressDocument > xDrawPages( mpDoc->getUnoModel() );
3358 Reference< XIndexAccess > xSlides( xDrawPages->getDrawPages(), UNO_QUERY_THROW );
3359 const sal_Int32 nNewSlideCount(xSlides.is() ? xSlides->getCount() : 0);
3361 if (nNewSlideCount != mpSlideController->getSlideNumberCount())
3363 // need to reinitialize AnimationSlideController
3364 OUString aPresSlide( maPresSettings.maPresPage );
3365 createSlideList( maPresSettings.mbAll, aPresSlide );
3368 // Check if current slide before change is still valid (maybe removed)
3369 const sal_Int32 nSlideCount(mpSlideController->getSlideNumberCount());
3370 bool bSlideStillValid(false);
3372 for (sal_Int32 nSlide(0); !bSlideStillValid && nSlide < nSlideCount; nSlide++)
3374 if (rXCurrentSlide == mpSlideController->getSlideByNumber(nSlide))
3376 bSlideStillValid = true;
3380 if(bSlideStillValid)
3382 // stay on that slide
3383 gotoSlide(rXCurrentSlide);
3385 else
3387 // not possible to stay on that slide, go to 1st slide (kinda restart)
3388 gotoFirstSlide();
3390 break;
3392 default:
3393 break;
3397 bool SlideshowImpl::isCurrentSlideInvolved(const SdrHint& rHint)
3399 // get current slide
3400 uno::Reference< css::drawing::XDrawPage > XCurrentSlide(getCurrentSlide());
3401 if (!XCurrentSlide.is())
3402 return false;
3404 SdrPage* pCurrentSlide(GetSdrPageFromXDrawPage(XCurrentSlide));
3405 if (nullptr == pCurrentSlide)
3406 return false;
3408 const SdrPage* pHintPage(rHint.GetPage());
3409 if (nullptr == pHintPage)
3410 return false;
3412 if (pHintPage->IsMasterPage())
3414 if (pCurrentSlide->TRG_HasMasterPage())
3416 // current slide uses MasterPage on which the change happened
3417 return pHintPage == &pCurrentSlide->TRG_GetMasterPage();
3421 // object on current slide was changed
3422 return pHintPage == pCurrentSlide;
3425 void SlideshowImpl::sendHintSlideChanged(const SdrPage* pChangedPage) const
3427 if (nullptr == pChangedPage)
3428 return;
3430 if (!mxShow.is())
3431 return;
3433 mxShow->setProperty(
3434 beans::PropertyValue( u"HintSlideChanged"_ustr ,
3436 Any( GetXDrawPageForSdrPage(const_cast<SdrPage*>(pChangedPage)) ),
3437 beans::PropertyState_DIRECT_VALUE ) );
3440 void SlideshowImpl::Notify(SfxBroadcaster& /*rBC*/, const SfxHint& rHint)
3442 if (SfxHintId::ThisIsAnSdrHint != rHint.GetId())
3443 // nothing to do for non-SdrHints
3444 return;
3446 if (nullptr == mpDoc)
3447 // better do nothing when no DrawModel (should not happen)
3448 return;
3450 // tdf#158664 I am surprised, but the 'this' instance keeps incarnated
3451 // when the slideshow was running once, so need to check for
3452 // SlideShow instance/running to be safe.
3453 // NOTE: isRunning() checks mxShow.is(), that is what we want
3454 if (!isRunning())
3455 // no SlideShow instance or not running, nothing to do
3456 return;
3458 const SdrHint& rSdrHint(static_cast<const SdrHint&>(rHint));
3459 const SdrHintKind eHintKind(rSdrHint.GetKind());
3461 switch (eHintKind)
3463 case SdrHintKind::ObjectInserted:
3465 if (nullptr != mnEventObjectInserted)
3466 // avoid multiple events
3467 return;
3469 // tdf#160669 IASS: inform about ALL changed slides due to prefetch
3470 sendHintSlideChanged(rSdrHint.GetPage());
3472 if (!isCurrentSlideInvolved(rSdrHint))
3473 // nothing to do when current slide is not involved
3474 return;
3476 // Refresh current slide
3477 uno::Reference< css::drawing::XDrawPage > XCurrentSlide(getCurrentSlide());
3478 mnEventObjectInserted = AsyncUpdateSlideshow_Impl::AsyncUpdateSlideshow(this, XCurrentSlide, eHintKind);
3479 break;
3481 case SdrHintKind::ObjectRemoved:
3483 if (nullptr != mnEventObjectRemoved)
3484 // avoid multiple events
3485 return;
3487 // tdf#160669 IASS: inform about ALL changed slides due to prefetch
3488 sendHintSlideChanged(rSdrHint.GetPage());
3490 if (!isCurrentSlideInvolved(rSdrHint))
3491 // nothing to do when current slide is not involved
3492 return;
3494 // Refresh current slide
3495 uno::Reference< css::drawing::XDrawPage > XCurrentSlide(getCurrentSlide());
3496 mnEventObjectRemoved = AsyncUpdateSlideshow_Impl::AsyncUpdateSlideshow(this, XCurrentSlide, eHintKind);
3497 break;
3499 case SdrHintKind::ObjectChange:
3501 if (nullptr != mnEventObjectChange)
3502 // avoid multiple events
3503 return;
3505 // tdf#160669 IASS: inform about ALL changed slides due to prefetch
3506 sendHintSlideChanged(rSdrHint.GetPage());
3508 if (!isCurrentSlideInvolved(rSdrHint))
3509 // nothing to do when current slide is not involved
3510 return;
3512 // Refresh current slide. Need to do that asynchronous, else e.g.
3513 // text edit changes EditEngine/Outliner are not progressed far
3514 // enough (ObjectChanged broadcast which we are in here seems
3515 // too early for some cases)
3516 uno::Reference< css::drawing::XDrawPage > XCurrentSlide(getCurrentSlide());
3517 mnEventObjectChange = AsyncUpdateSlideshow_Impl::AsyncUpdateSlideshow(this, XCurrentSlide, eHintKind);
3518 break;
3520 case SdrHintKind::PageOrderChange:
3522 // Unfortunately we get multiple events, e.g. when drag/drop position change in
3523 // slide sorter on left side of EditView. This includes some with page number +1,
3524 // then again -1 (it's a position change). Problem is that in-between already
3525 // a re-schedule seems to happen, so indeed AsyncNotifyEvent will change to +1/-1
3526 // already. Since we get even more, at least try to take the last one. I found no
3527 // good solution yet for this.
3528 if (nullptr != mnEventPageOrderChange)
3529 Application::RemoveUserEvent( mnEventPageOrderChange );
3531 // tdf#160669 IASS: inform about ALL changed slides due to prefetch
3532 sendHintSlideChanged(rSdrHint.GetPage());
3534 // order of pages (object pages or master pages) changed (Insert/Remove/ChangePos)
3535 uno::Reference< css::drawing::XDrawPage > XCurrentSlide(getCurrentSlide());
3536 mnEventPageOrderChange = AsyncUpdateSlideshow_Impl::AsyncUpdateSlideshow(this, XCurrentSlide, eHintKind);
3537 break;
3539 case SdrHintKind::ModelCleared:
3541 // immediately end presentation
3542 endPresentation();
3543 break;
3545 default:
3546 break;
3550 Reference< XSlideShow > SAL_CALL SlideshowImpl::getSlideShow()
3552 return mxShow;
3555 PresentationSettingsEx::PresentationSettingsEx( const PresentationSettingsEx& r )
3556 : PresentationSettings( r )
3557 , mbRehearseTimings(r.mbRehearseTimings)
3558 , mbPreview(r.mbPreview)
3559 , mpParentWindow( nullptr )
3563 PresentationSettingsEx::PresentationSettingsEx( PresentationSettings const & r )
3564 : PresentationSettings( r )
3565 , mbRehearseTimings(false)
3566 , mbPreview(false)
3567 , mpParentWindow(nullptr)
3571 void PresentationSettingsEx::SetArguments( const Sequence< PropertyValue >& rArguments )
3573 for( const PropertyValue& rValue : rArguments )
3575 SetPropertyValue( rValue.Name, rValue.Value );
3579 void PresentationSettingsEx::SetPropertyValue( std::u16string_view rProperty, const Any& rValue )
3581 if ( rProperty == u"RehearseTimings" )
3583 if( rValue >>= mbRehearseTimings )
3584 return;
3586 else if ( rProperty == u"Preview" )
3588 if( rValue >>= mbPreview )
3589 return;
3591 else if ( rProperty == u"AnimationNode" )
3593 if( rValue >>= mxAnimationNode )
3594 return;
3596 else if ( rProperty == u"ParentWindow" )
3598 Reference< XWindow > xWindow;
3599 if( rValue >>= xWindow )
3601 mpParentWindow = xWindow.is() ? VCLUnoHelper::GetWindow( xWindow )
3602 : nullptr;
3603 return;
3606 else if ( rProperty == u"AllowAnimations" )
3608 if( rValue >>= mbAnimationAllowed )
3609 return;
3611 else if ( rProperty == u"FirstPage" )
3613 OUString aPresPage;
3614 if( rValue >>= aPresPage )
3616 maPresPage = getUiNameFromPageApiNameImpl(aPresPage);
3617 mbCustomShow = false;
3618 mbAll = false;
3619 return;
3621 else
3623 if( rValue >>= mxStartPage )
3624 return;
3627 else if ( rProperty == u"IsAlwaysOnTop" )
3629 if( rValue >>= mbAlwaysOnTop )
3630 return;
3632 else if ( rProperty == u"IsAutomatic" )
3634 if( rValue >>= mbManual )
3635 return;
3637 else if ( rProperty == u"IsEndless" )
3639 if( rValue >>= mbEndless )
3640 return;
3642 else if ( rProperty == u"IsFullScreen" )
3644 if( rValue >>= mbFullScreen )
3645 return;
3647 else if ( rProperty == u"IsMouseVisible" )
3649 if( rValue >>= mbMouseVisible )
3650 return;
3652 else if ( rProperty == u"Pause" )
3654 sal_Int32 nPause = -1;
3655 if( (rValue >>= nPause) && (nPause >= 0) )
3657 mnPauseTimeout = nPause;
3658 return;
3661 else if ( rProperty == u"UsePen" )
3663 if( rValue >>= mbMouseAsPen )
3664 return;
3666 throw IllegalArgumentException();
3669 // XAnimationListener
3671 SlideShowListenerProxy::SlideShowListenerProxy( rtl::Reference< SlideshowImpl > xController, css::uno::Reference< css::presentation::XSlideShow > xSlideShow )
3672 : mxController(std::move( xController ))
3673 , mxSlideShow(std::move( xSlideShow ))
3677 SlideShowListenerProxy::~SlideShowListenerProxy()
3681 void SlideShowListenerProxy::addAsSlideShowListener()
3683 if( mxSlideShow.is() )
3685 Reference< XSlideShowListener > xSlideShowListener( this );
3686 mxSlideShow->addSlideShowListener( xSlideShowListener );
3690 void SlideShowListenerProxy::removeAsSlideShowListener()
3692 if( mxSlideShow.is() )
3694 Reference< XSlideShowListener > xSlideShowListener( this );
3695 mxSlideShow->removeSlideShowListener( xSlideShowListener );
3699 void SlideShowListenerProxy::addShapeEventListener( const css::uno::Reference< css::drawing::XShape >& xShape )
3701 if( mxSlideShow.is() )
3703 Reference< XShapeEventListener > xListener( this );
3704 mxSlideShow->addShapeEventListener( xListener, xShape );
3708 void SlideShowListenerProxy::removeShapeEventListener( const css::uno::Reference< css::drawing::XShape >& xShape )
3710 if( mxSlideShow.is() )
3712 Reference< XShapeEventListener > xListener( this );
3713 mxSlideShow->removeShapeEventListener( xListener, xShape );
3717 void SlideShowListenerProxy::addSlideShowListener( const css::uno::Reference< css::presentation::XSlideShowListener >& xListener )
3719 std::unique_lock g(m_aMutex);
3720 maListeners.addInterface(g, xListener);
3723 void SlideShowListenerProxy::removeSlideShowListener( const css::uno::Reference< css::presentation::XSlideShowListener >& xListener )
3725 std::unique_lock g(m_aMutex);
3726 maListeners.removeInterface(g, xListener);
3729 void SAL_CALL SlideShowListenerProxy::beginEvent( const Reference< XAnimationNode >& xNode )
3731 std::unique_lock aGuard( m_aMutex );
3733 if( maListeners.getLength(aGuard) >= 0 )
3735 maListeners.forEach(aGuard,
3736 [&] (Reference<XAnimationListener> const& xListener) {
3737 return xListener->beginEvent(xNode);
3738 } );
3742 void SAL_CALL SlideShowListenerProxy::endEvent( const Reference< XAnimationNode >& xNode )
3744 std::unique_lock aGuard( m_aMutex );
3746 if( maListeners.getLength(aGuard) >= 0 )
3748 maListeners.forEach(aGuard,
3749 [&] (Reference<XAnimationListener> const& xListener) {
3750 return xListener->endEvent(xNode);
3751 } );
3755 void SAL_CALL SlideShowListenerProxy::repeat( const Reference< XAnimationNode >& xNode, ::sal_Int32 nRepeat )
3757 std::unique_lock aGuard( m_aMutex );
3759 if( maListeners.getLength(aGuard) >= 0 )
3761 maListeners.forEach(aGuard,
3762 [&] (Reference<XAnimationListener> const& xListener) {
3763 return xListener->repeat(xNode, nRepeat);
3764 } );
3768 // css::presentation::XSlideShowListener:
3770 void SAL_CALL SlideShowListenerProxy::paused( )
3772 std::unique_lock aGuard( m_aMutex );
3774 maListeners.forEach(aGuard,
3775 [](uno::Reference<presentation::XSlideShowListener> const& xListener)
3777 xListener->paused();
3781 void SAL_CALL SlideShowListenerProxy::resumed( )
3783 std::unique_lock aGuard( m_aMutex );
3785 maListeners.forEach(aGuard,
3786 [](uno::Reference<presentation::XSlideShowListener> const& xListener)
3788 xListener->resumed();
3792 void SAL_CALL SlideShowListenerProxy::slideTransitionStarted( )
3794 std::unique_lock aGuard( m_aMutex );
3796 maListeners.forEach(aGuard,
3797 [](uno::Reference<presentation::XSlideShowListener> const& xListener)
3799 xListener->slideTransitionStarted();
3803 void SAL_CALL SlideShowListenerProxy::slideTransitionEnded( )
3805 std::unique_lock aGuard( m_aMutex );
3807 maListeners.forEach(aGuard,
3808 [](uno::Reference<presentation::XSlideShowListener> const& xListener)
3810 xListener->slideTransitionEnded ();
3814 void SAL_CALL SlideShowListenerProxy::slideAnimationsEnded( )
3816 std::unique_lock aGuard( m_aMutex );
3818 maListeners.forEach(aGuard,
3819 [](uno::Reference<presentation::XSlideShowListener> const& xListener)
3821 xListener->slideAnimationsEnded ();
3825 void SlideShowListenerProxy::slideEnded(sal_Bool bReverse)
3828 std::unique_lock aGuard( m_aMutex );
3830 if( maListeners.getLength(aGuard) >= 0 )
3832 maListeners.forEach(aGuard,
3833 [&] (Reference<XSlideShowListener> const& xListener) {
3834 return xListener->slideEnded(bReverse);
3835 } );
3840 SolarMutexGuard aSolarGuard;
3841 if( mxController.is() )
3842 mxController->slideEnded(bReverse);
3846 void SlideShowListenerProxy::hyperLinkClicked( OUString const& aHyperLink )
3849 std::unique_lock aGuard( m_aMutex );
3851 if( maListeners.getLength(aGuard) >= 0 )
3853 maListeners.forEach(aGuard,
3854 [&] (Reference<XSlideShowListener> const& xListener) {
3855 return xListener->hyperLinkClicked(aHyperLink);
3856 } );
3861 SolarMutexGuard aSolarGuard;
3862 if( mxController.is() )
3863 mxController->hyperLinkClicked(aHyperLink);
3867 // XEventListener
3869 void SAL_CALL SlideShowListenerProxy::disposing( const css::lang::EventObject& aDisposeEvent )
3871 std::unique_lock g(m_aMutex);
3872 maListeners.disposeAndClear( g, aDisposeEvent );
3873 mxController.clear();
3874 mxSlideShow.clear();
3877 // XShapeEventListener
3879 void SAL_CALL SlideShowListenerProxy::click( const Reference< XShape >& xShape, const css::awt::MouseEvent& /*aOriginalEvent*/ )
3881 SolarMutexGuard aSolarGuard;
3882 if( mxController.is() )
3883 mxController->click(xShape );
3886 void SAL_CALL SlideShowListenerProxy::contextMenuShow(const css::awt::Point& point)
3888 SolarMutexGuard aSolarGuard;
3889 if (mxController.is())
3890 mxController->contextMenuShow(point);
3893 } // namespace ::sd
3895 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */