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