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 <officecfg/Office/Common.hxx> 41 #include <svl/stritem.hxx> 42 #include <svl/urihelper.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/svdoole2.hxx> 54 #include <svx/f3dchild.hxx> 55 #include <svx/imapdlg.hxx> 56 #include <svx/fontwork.hxx> 57 #include <svx/SvxColorChildWindow.hxx> 58 #include <svx/bmpmask.hxx> 59 #include <svx/srchdlg.hxx> 60 #include <svx/hyperdlg.hxx> 61 #include <svx/svxids.hrc> 62 #include <AnimationChildWindow.hxx> 63 #include <notifydocumentevent.hxx> 64 #include "slideshowimpl.hxx" 65 #include "slideshowviewimpl.hxx" 66 #include "PaneHider.hxx" 67 68 #include <bitmaps.hlst> 69 #include <strings.hrc> 70 #include <sdresid.hxx> 71 #include <vcl/canvastools.hxx> 72 #include <vcl/commandevent.hxx> 73 #include <vcl/weldutils.hxx> 74 75 #include <vcl/settings.hxx> 76 #include <vcl/svapp.hxx> 77 #include <vcl/help.hxx> 78 #include <comphelper/processfactory.hxx> 79 #include <comphelper/propertyvalue.hxx> 80 #include <rtl/ref.hxx> 81 #include <o3tl/safeint.hxx> 82 #include <o3tl/string_view.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 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 137 sal_Int32 getSlideIndexCount() const { return maSlideNumbers.size(); } 138 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 164 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 170 bool isValidIndex( sal_Int32 nIndex ) const { return (nIndex >= 0) && (o3tl::make_unsigned(nIndex) < maSlideNumbers.size()); } 171 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 186 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 194 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 204 void AnimationSlideController::setPreviewNode( const Reference< XAnimationNode >& xPreviewNode ) 205 { 206 mxPreviewNode = xPreviewNode; 207 } 208 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 221 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 238 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 248 sal_Int32 AnimationSlideController::getCurrentSlideIndex() const 249 { 250 if( mnHiddenSlideNumber != -1 ) 251 return -1; 252 else 253 return mnCurrentSlideIndex; 254 } 255 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 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 290 sal_Int32 AnimationSlideController::getSlideNumber( sal_Int32 nSlideIndex ) const 291 { 292 if( isValidIndex( nSlideIndex ) ) 293 return maSlideNumbers[nSlideIndex]; 294 else 295 return -1; 296 } 297 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 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 335 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 349 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 387 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 400 bool AnimationSlideController::nextSlide() 401 { 402 return jumpToSlideIndex( getNextSlideIndex() ); 403 } 404 405 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 436 bool AnimationSlideController::previousSlide() 437 { 438 return jumpToSlideIndex( getPreviousSlideIndex() ); 439 } 440 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{ Any(xSlide), Any(xAnimNode) }; 458 aProperties.emplace_back( "Prefetch" , 459 -1, 460 Any(aValue), 461 PropertyState_DIRECT_VALUE); 462 } 463 if (bSkipAllMainSequenceEffects) 464 { 465 // Add one property that prevents the slide transition from being 466 // shown (to speed up the transition to the previous slide) and 467 // one to show all main sequence effects so that the user can 468 // continue to undo effects. 469 aProperties.emplace_back( "SkipAllMainSequenceEffects", 470 -1, 471 Any(true), 472 PropertyState_DIRECT_VALUE); 473 aProperties.emplace_back("SkipSlideTransition", 474 -1, 475 Any(true), 476 PropertyState_DIRECT_VALUE); 477 } 478 479 if( getSlideAPI( nCurrentSlideNumber, xSlide, xAnimNode ) ) 480 xShow->displaySlide( xSlide, xDrawPages, xAnimNode, comphelper::containerToSequence(aProperties) ); 481 } 482 483 constexpr OUStringLiteral gsOnClick( u"OnClick" ); 484 constexpr OUStringLiteral gsBookmark( u"Bookmark" ); 485 constexpr OUStringLiteral gsVerb( u"Verb" ); 486 487 SlideshowImpl::SlideshowImpl( const Reference< XPresentation2 >& xPresentation, ViewShell* pViewSh, ::sd::View* pView, SdDrawDocument* pDoc, vcl::Window* pParentWindow ) 488 : mxModel(pDoc->getUnoModel(),UNO_QUERY_THROW) 489 , maUpdateTimer("SlideShowImpl maUpdateTimer") 490 , maInputFreezeTimer("SlideShowImpl maInputFreezeTimer") 491 , maDeactivateTimer("SlideShowImpl maDeactivateTimer") 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.SetInvokeHandler(LINK(this, SlideshowImpl, updateHdl)); 522 // Priority must not be too high or we'll starve input handling etc. 523 maUpdateTimer.SetPriority(TaskPriority::REPAINT); 524 525 maDeactivateTimer.SetInvokeHandler(LINK(this, SlideshowImpl, deactivateHdl)); 526 maDeactivateTimer.SetTimeout( 20 ); 527 528 maInputFreezeTimer.SetInvokeHandler( LINK( this, SlideshowImpl, ReadyForNextInputHdl ) ); 529 maInputFreezeTimer.SetTimeout( 20 ); 530 531 // no autosave during show 532 if( officecfg::Office::Common::Save::Document::AutoSave::get() ) 533 mbAutoSaveWasOn = true; 534 535 Application::AddEventListener( LINK( this, SlideshowImpl, EventListenerHdl ) ); 536 537 mbUsePen = maPresSettings.mbMouseAsPen; 538 539 SdOptions* pOptions = SD_MOD()->GetSdOptions(DocumentType::Impress); 540 if( pOptions ) 541 { 542 mnUserPaintColor = pOptions->GetPresentationPenColor(); 543 mdUserPaintStrokeWidth = pOptions->GetPresentationPenWidth(); 544 } 545 } 546 547 SlideshowImpl::~SlideshowImpl() 548 { 549 SdModule *pModule = SD_MOD(); 550 //rhbz#806663 SlideshowImpl can outlive SdModule 551 SdOptions* pOptions = pModule ? 552 pModule->GetSdOptions(DocumentType::Impress) : nullptr; 553 if( pOptions ) 554 { 555 pOptions->SetPresentationPenColor(mnUserPaintColor); 556 pOptions->SetPresentationPenWidth(mdUserPaintStrokeWidth); 557 } 558 559 Application::RemoveEventListener( LINK( this, SlideshowImpl, EventListenerHdl ) ); 560 561 maDeactivateTimer.Stop(); 562 563 if( !mbDisposed ) 564 { 565 OSL_FAIL("SlideshowImpl::~SlideshowImpl(), component was not disposed!"); 566 std::unique_lock g(m_aMutex); 567 disposing(g); 568 } 569 } 570 571 void SlideshowImpl::disposing(std::unique_lock<std::mutex>&) 572 { 573 #ifdef ENABLE_SDREMOTE 574 RemoteServer::presentationStopped(); 575 #endif 576 if( mxShow.is() && mpDoc ) 577 NotifyDocumentEvent( 578 *mpDoc, 579 "OnEndPresentation" ); 580 581 if( mbAutoSaveWasOn ) 582 setAutoSaveState( true ); 583 584 if( mnEndShowEvent ) 585 Application::RemoveUserEvent( mnEndShowEvent ); 586 if( mnContextMenuEvent ) 587 Application::RemoveUserEvent( mnContextMenuEvent ); 588 589 maInputFreezeTimer.Stop(); 590 591 SolarMutexGuard aSolarGuard; 592 593 if( !mxShow.is() ) 594 return; 595 596 if( mxPresentation.is() ) 597 mxPresentation->end(); 598 599 maUpdateTimer.Stop(); 600 601 removeShapeEvents(); 602 603 if( mxListenerProxy.is() ) 604 mxListenerProxy->removeAsSlideShowListener(); 605 606 try 607 { 608 if( mxView.is() ) 609 mxShow->removeView( mxView ); 610 611 Reference< XComponent > xComponent( mxShow, UNO_QUERY ); 612 if( xComponent.is() ) 613 xComponent->dispose(); 614 615 if( mxView.is() ) 616 mxView->dispose(); 617 } 618 catch( Exception& ) 619 { 620 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::stop()" ); 621 } 622 623 mxShow.clear(); 624 mxView.clear(); 625 mxListenerProxy.clear(); 626 mpSlideController.reset(); 627 628 // take DrawView from presentation window, but give the old window back 629 if( mpShowWindow && mpView ) 630 mpView->DeleteWindowFromPaintView( mpShowWindow->GetOutDev() ); 631 632 if( mpView ) 633 mpView->SetAnimationPause( false ); 634 635 if( mpViewShell ) 636 { 637 mpViewShell->SetActiveWindow(mpOldActiveWindow); 638 if (mpShowWindow) 639 mpShowWindow->SetViewShell( nullptr ); 640 } 641 642 if( mpView ) 643 mpView->InvalidateAllWin(); 644 645 if( maPresSettings.mbFullScreen ) 646 { 647 #if HAVE_FEATURE_SCRIPTING 648 // restore StarBASICErrorHdl 649 StarBASIC::SetGlobalErrorHdl(maStarBASICGlobalErrorHdl); 650 maStarBASICGlobalErrorHdl = Link<StarBASIC*,bool>(); 651 #endif 652 } 653 else 654 { 655 if( mpShowWindow ) 656 mpShowWindow->Hide(); 657 } 658 659 if( meAnimationMode == ANIMATIONMODE_SHOW ) 660 { 661 mpDocSh->SetSlotFilter(); 662 mpDocSh->ApplySlotFilter(); 663 664 Help::EnableContextHelp(); 665 Help::EnableExtHelp(); 666 667 showChildWindows(); 668 mnChildMask = 0; 669 } 670 671 // show current window again 672 if( mpViewShell && dynamic_cast< PresentationViewShell *>( mpViewShell ) == nullptr) 673 { 674 if( meAnimationMode == ANIMATIONMODE_SHOW ) 675 { 676 mpViewShell->GetViewShellBase().ShowUIControls (true); 677 mpPaneHider.reset(); 678 } 679 else if( meAnimationMode == ANIMATIONMODE_PREVIEW ) 680 { 681 mpViewShell->ShowUIControls(true); 682 } 683 } 684 685 if( mpShowWindow ) 686 mpShowWindow->Hide(); 687 mpShowWindow.disposeAndClear(); 688 689 if ( mpViewShell ) 690 { 691 if( meAnimationMode == ANIMATIONMODE_SHOW ) 692 { 693 ::sd::Window* pActWin = mpViewShell->GetActiveWindow(); 694 695 if (pActWin) 696 { 697 Size aVisSizePixel = pActWin->GetOutputSizePixel(); 698 ::tools::Rectangle aVisAreaWin = pActWin->PixelToLogic( ::tools::Rectangle( Point(0,0), aVisSizePixel) ); 699 mpViewShell->VisAreaChanged(aVisAreaWin); 700 if (mpView) 701 mpView->VisAreaChanged(pActWin->GetOutDev()); 702 pActWin->GrabFocus(); 703 } 704 } 705 706 // restart the custom show dialog if he started us 707 if( mpViewShell->IsStartShowWithDialog() && getDispatcher() ) 708 { 709 mpViewShell->SetStartShowWithDialog( false ); 710 getDispatcher()->Execute( SID_CUSTOMSHOW_DLG, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD ); 711 } 712 713 mpViewShell->GetViewShellBase().UpdateBorder(true); 714 } 715 716 if( mpShowWindow ) 717 { 718 mpShowWindow.disposeAndClear(); 719 } 720 721 setActiveXToolbarsVisible( true ); 722 723 mbDisposed = true; 724 } 725 726 bool SlideshowImpl::startPreview( 727 const Reference< XDrawPage >& xDrawPage, 728 const Reference< XAnimationNode >& xAnimationNode, 729 vcl::Window * pParent ) 730 { 731 bool bRet = false; 732 733 try 734 { 735 const Reference<lang::XServiceInfo> xServiceInfo( xDrawPage, UNO_QUERY ); 736 if (xServiceInfo.is()) { 737 const Sequence<OUString> supportedServices( 738 xServiceInfo->getSupportedServiceNames() ); 739 if (comphelper::findValue(supportedServices, "com.sun.star.drawing.MasterPage") != -1) { 740 OSL_FAIL("sd::SlideshowImpl::startPreview() " 741 "not allowed on master page!"); 742 return false; 743 } 744 } 745 746 mxPreviewDrawPage = xDrawPage; 747 mxPreviewAnimationNode = xAnimationNode; 748 meAnimationMode = ANIMATIONMODE_PREVIEW; 749 750 maPresSettings.mbAll = false; 751 maPresSettings.mbEndless = false; 752 maPresSettings.mbCustomShow = false; 753 maPresSettings.mbManual = false; 754 maPresSettings.mbMouseVisible = false; 755 maPresSettings.mbMouseAsPen = false; 756 maPresSettings.mbLockedPages = false; 757 maPresSettings.mbAlwaysOnTop = false; 758 maPresSettings.mbFullScreen = false; 759 maPresSettings.mbAnimationAllowed = true; 760 maPresSettings.mnPauseTimeout = 0; 761 maPresSettings.mbShowPauseLogo = false; 762 763 Reference< XDrawPagesSupplier > xDrawPages( mpDoc->getUnoModel(), UNO_QUERY_THROW ); 764 Reference< XIndexAccess > xSlides( xDrawPages->getDrawPages(), UNO_QUERY_THROW ); 765 mpSlideController = std::make_shared<AnimationSlideController>( xSlides, AnimationSlideController::PREVIEW ); 766 767 sal_Int32 nSlideNumber = 0; 768 Reference< XPropertySet > xSet( mxPreviewDrawPage, UNO_QUERY_THROW ); 769 xSet->getPropertyValue( "Number" ) >>= nSlideNumber; 770 mpSlideController->insertSlideNumber( nSlideNumber-1 ); 771 mpSlideController->setPreviewNode( xAnimationNode ); 772 773 mpShowWindow = VclPtr<ShowWindow>::Create( this, ((pParent == nullptr) && mpViewShell) ? mpParentWindow.get() : pParent ); 774 if( mpViewShell ) 775 { 776 mpViewShell->SetActiveWindow( mpShowWindow ); 777 mpShowWindow->SetViewShell (mpViewShell); 778 mpViewShell->ShowUIControls (false); 779 } 780 781 if( mpView ) 782 { 783 mpView->AddWindowToPaintView( mpShowWindow->GetOutDev(), nullptr ); 784 mpView->SetAnimationPause( true ); 785 } 786 787 // call resize handler 788 if( pParent ) 789 { 790 maPresSize = pParent->GetSizePixel(); 791 } 792 else if( mpViewShell ) 793 { 794 ::tools::Rectangle aContentRect (mpViewShell->GetViewShellBase().getClientRectangle()); 795 if (AllSettings::GetLayoutRTL()) 796 { 797 aContentRect.SetLeft( aContentRect.Right() ); 798 aContentRect.AdjustRight(aContentRect.Right() ); 799 } 800 maPresSize = aContentRect.GetSize(); 801 mpShowWindow->SetPosPixel( aContentRect.TopLeft() ); 802 } 803 else 804 { 805 OSL_FAIL("sd::SlideshowImpl::startPreview(), I need either a parent window or a viewshell!"); 806 } 807 resize( maPresSize ); 808 809 sal_Int32 nPropertyCount = 1; 810 if( mxPreviewAnimationNode.is() ) 811 nPropertyCount++; 812 813 Sequence< beans::PropertyValue > aProperties(nPropertyCount); 814 auto pProperties = aProperties.getArray(); 815 pProperties[0].Name = "AutomaticAdvancement"; 816 pProperties[0].Value <<= 1.0; // one second timeout 817 818 if( mxPreviewAnimationNode.is() ) 819 { 820 pProperties[1].Name = "NoSlideTransitions"; 821 pProperties[1].Value <<= true; 822 } 823 824 bRet = startShowImpl( aProperties ); 825 826 if( mpShowWindow != nullptr && meAnimationMode == ANIMATIONMODE_PREVIEW ) 827 mpShowWindow->SetPreviewMode(); 828 829 } 830 catch( Exception& ) 831 { 832 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::startPreview()" ); 833 bRet = false; 834 } 835 836 return bRet; 837 } 838 839 bool SlideshowImpl::startShow( PresentationSettingsEx const * pPresSettings ) 840 { 841 const rtl::Reference<SlideshowImpl> xKeepAlive(this); 842 843 DBG_ASSERT( !mxShow.is(), "sd::SlideshowImpl::startShow(), called twice!" ); 844 if( mxShow.is() ) 845 return true; 846 DBG_ASSERT( mpParentWindow!=nullptr, "sd::SlideshowImpl::startShow() called without parent window" ); 847 if (mpParentWindow == nullptr) 848 return false; 849 850 // Autoplay (pps/ppsx) 851 if (mpViewShell->GetDoc()->IsStartWithPresentation()){ 852 mpViewShell->GetDoc()->SetExitAfterPresenting(true); 853 } 854 855 bool bRet = false; 856 857 try 858 { 859 if( pPresSettings ) 860 { 861 maPresSettings = *pPresSettings; 862 mbRehearseTimings = pPresSettings->mbRehearseTimings; 863 } 864 865 OUString aPresSlide( maPresSettings.maPresPage ); 866 SdPage* pStartPage = mpViewShell->GetActualPage(); 867 bool bStartWithActualSlide = pStartPage; 868 869 // times should be measured? 870 if( mbRehearseTimings ) 871 { 872 maPresSettings.mbEndless = false; 873 maPresSettings.mbManual = true; 874 maPresSettings.mbMouseVisible = true; 875 maPresSettings.mbMouseAsPen = false; 876 maPresSettings.mnPauseTimeout = 0; 877 maPresSettings.mbShowPauseLogo = false; 878 } 879 880 if( pStartPage ) 881 { 882 if( pStartPage->GetPageKind() == PageKind::Notes ) 883 { 884 // we are in notes page mode, so get 885 // the corresponding draw page 886 const sal_uInt16 nPgNum = ( pStartPage->GetPageNum() - 2 ) >> 1; 887 pStartPage = mpDoc->GetSdPage( nPgNum, PageKind::Standard ); 888 } 889 } 890 891 if( bStartWithActualSlide ) 892 { 893 if ( aPresSlide.isEmpty()) 894 { 895 // no preset slide yet, so pick current on one 896 aPresSlide = pStartPage->GetName(); 897 // if the starting slide is hidden, we can't set slide controller to ALL mode 898 maPresSettings.mbAll = !pStartPage->IsExcluded(); 899 } 900 901 if( meAnimationMode != ANIMATIONMODE_SHOW ) 902 { 903 if( pStartPage->GetPageKind() == PageKind::Standard ) 904 { 905 maPresSettings.mbAll = false; 906 } 907 } 908 } 909 910 // build page list 911 createSlideList( maPresSettings.mbAll, aPresSlide ); 912 913 // remember Slide number from where the show was started 914 if( pStartPage ) 915 mnRestoreSlide = ( pStartPage->GetPageNum() - 1 ) / 2; 916 917 if( mpSlideController->hasSlides() ) 918 { 919 // hide child windows 920 hideChildWindows(); 921 922 mpShowWindow = VclPtr<ShowWindow>::Create( this, mpParentWindow ); 923 mpShowWindow->SetMouseAutoHide( !maPresSettings.mbMouseVisible ); 924 mpViewShell->SetActiveWindow( mpShowWindow ); 925 mpShowWindow->SetViewShell (mpViewShell); 926 mpViewShell->GetViewShellBase().ShowUIControls (false); 927 // Hide the side panes for in-place presentations. 928 if ( ! maPresSettings.mbFullScreen) 929 mpPaneHider.reset(new PaneHider(*mpViewShell,this)); 930 931 // these Slots are forbidden in other views for this document 932 if( mpDocSh ) 933 { 934 mpDocSh->SetSlotFilter( true, pAllowed ); 935 mpDocSh->ApplySlotFilter(); 936 } 937 938 Help::DisableContextHelp(); 939 Help::DisableExtHelp(); 940 941 if( maPresSettings.mbFullScreen ) 942 { 943 #if HAVE_FEATURE_SCRIPTING 944 // disable basic ide error handling 945 maStarBASICGlobalErrorHdl = StarBASIC::GetGlobalErrorHdl(); 946 StarBASIC::SetGlobalErrorHdl( Link<StarBASIC*,bool>() ); 947 #endif 948 } 949 950 // call resize handler 951 maPresSize = mpParentWindow->GetSizePixel(); 952 if (!maPresSettings.mbFullScreen) 953 { 954 const ::tools::Rectangle& aClientRect = mpViewShell->GetViewShellBase().getClientRectangle(); 955 maPresSize = aClientRect.GetSize(); 956 mpShowWindow->SetPosPixel( aClientRect.TopLeft() ); 957 resize( maPresSize ); 958 } 959 960 // #i41824# 961 // Note: In FullScreen Mode the OS (window manager) sends a resize to 962 // the WorkWindow once it actually resized it to full size. The 963 // WorkWindow propagates the resize to the DrawViewShell which calls 964 // resize() at the SlideShow (this). Calling resize here results in a 965 // temporary display of a black window in the window's default size 966 967 if( mpView ) 968 { 969 mpView->AddWindowToPaintView( mpShowWindow->GetOutDev(), nullptr ); 970 mpView->SetAnimationPause( true ); 971 } 972 973 SfxBindings* pBindings = getBindings(); 974 if( pBindings ) 975 { 976 pBindings->Invalidate( SID_PRESENTATION ); 977 pBindings->Invalidate( SID_REHEARSE_TIMINGS ); 978 } 979 980 // Defer the sd::ShowWindow's GrabFocus to SlideShow::activate. so that the accessible event can be fired correctly. 981 //mpShowWindow->GrabFocus(); 982 983 std::vector<beans::PropertyValue> aProperties; 984 aProperties.reserve( 4 ); 985 986 aProperties.emplace_back( "AdvanceOnClick" , 987 -1, Any( !maPresSettings.mbLockedPages ), 988 beans::PropertyState_DIRECT_VALUE ); 989 990 aProperties.emplace_back( "ImageAnimationsAllowed" , 991 -1, Any( maPresSettings.mbAnimationAllowed ), 992 beans::PropertyState_DIRECT_VALUE ); 993 994 const bool bZOrderEnabled( 995 SD_MOD()->GetSdOptions( mpDoc->GetDocumentType() )->IsSlideshowRespectZOrder() ); 996 aProperties.emplace_back( "DisableAnimationZOrder" , 997 -1, Any( !bZOrderEnabled ), 998 beans::PropertyState_DIRECT_VALUE ); 999 1000 aProperties.emplace_back( "ForceManualAdvance" , 1001 -1, Any( maPresSettings.mbManual ), 1002 beans::PropertyState_DIRECT_VALUE ); 1003 1004 if( mbUsePen ) 1005 { 1006 aProperties.emplace_back( "UserPaintColor" , 1007 // User paint color is black by default. 1008 -1, Any( mnUserPaintColor ), 1009 beans::PropertyState_DIRECT_VALUE ); 1010 1011 aProperties.emplace_back( "UserPaintStrokeWidth" , 1012 // User paint color is black by default. 1013 -1, Any( mdUserPaintStrokeWidth ), 1014 beans::PropertyState_DIRECT_VALUE ); 1015 } 1016 1017 if (mbRehearseTimings) { 1018 aProperties.emplace_back( "RehearseTimings" , 1019 -1, Any(true), beans::PropertyState_DIRECT_VALUE ); 1020 } 1021 1022 bRet = startShowImpl( Sequence<beans::PropertyValue>( 1023 aProperties.data(), aProperties.size() ) ); 1024 1025 } 1026 1027 setActiveXToolbarsVisible( false ); 1028 } 1029 catch (const Exception&) 1030 { 1031 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::startShow()" ); 1032 bRet = false; 1033 } 1034 1035 return bRet; 1036 } 1037 1038 bool SlideshowImpl::startShowImpl( const Sequence< beans::PropertyValue >& aProperties ) 1039 { 1040 try 1041 { 1042 mxShow.set( createSlideShow(), UNO_SET_THROW ); 1043 1044 mxView = new SlideShowView( 1045 *mpShowWindow, 1046 mpDoc, 1047 meAnimationMode, 1048 this, 1049 maPresSettings.mbFullScreen); 1050 1051 // try add wait symbol to properties: 1052 const Reference<rendering::XSpriteCanvas> xSpriteCanvas( 1053 mxView->getCanvas() ); 1054 if (xSpriteCanvas.is()) 1055 { 1056 BitmapEx waitSymbolBitmap(BMP_WAIT_ICON); 1057 const Reference<rendering::XBitmap> xBitmap( 1058 vcl::unotools::xBitmapFromBitmapEx( waitSymbolBitmap ) ); 1059 if (xBitmap.is()) 1060 { 1061 mxShow->setProperty( 1062 beans::PropertyValue( "WaitSymbolBitmap" , 1063 -1, 1064 Any( xBitmap ), 1065 beans::PropertyState_DIRECT_VALUE ) ); 1066 } 1067 1068 BitmapEx pointerSymbolBitmap(BMP_POINTER_ICON); 1069 const Reference<rendering::XBitmap> xPointerBitmap( 1070 vcl::unotools::xBitmapFromBitmapEx( pointerSymbolBitmap ) ); 1071 if (xPointerBitmap.is()) 1072 { 1073 mxShow->setProperty( 1074 beans::PropertyValue( "PointerSymbolBitmap" , 1075 -1, 1076 Any( xPointerBitmap ), 1077 beans::PropertyState_DIRECT_VALUE ) ); 1078 } 1079 } 1080 1081 for( const auto& rProp : aProperties ) 1082 mxShow->setProperty( rProp ); 1083 1084 mxShow->addView( mxView ); 1085 1086 mxListenerProxy.set( new SlideShowListenerProxy( this, mxShow ) ); 1087 mxListenerProxy->addAsSlideShowListener(); 1088 1089 NotifyDocumentEvent( 1090 *mpDoc, 1091 "OnStartPresentation"); 1092 displaySlideIndex( mpSlideController->getStartSlideIndex() ); 1093 1094 return true; 1095 } 1096 catch( Exception& ) 1097 { 1098 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::startShowImpl()" ); 1099 return false; 1100 } 1101 } 1102 1103 /** called only by the slideshow view when the first paint event occurs. 1104 This actually starts the slideshow. */ 1105 void SlideshowImpl::onFirstPaint() 1106 { 1107 if( mpShowWindow ) 1108 { 1109 /* 1110 mpShowWindow->SetBackground( Wallpaper( COL_BLACK ) ); 1111 mpShowWindow->Erase(); 1112 mpShowWindow->SetBackground(); 1113 */ 1114 } 1115 1116 SolarMutexGuard aSolarGuard; 1117 maUpdateTimer.SetTimeout( sal_uLong(100) ); 1118 maUpdateTimer.Start(); 1119 } 1120 1121 void SlideshowImpl::paint() 1122 { 1123 if( mxView.is() ) try 1124 { 1125 awt::PaintEvent aEvt; 1126 // aEvt.UpdateRect = TODO 1127 mxView->paint( aEvt ); 1128 } 1129 catch( Exception& ) 1130 { 1131 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::paint()" ); 1132 } 1133 } 1134 1135 void SAL_CALL SlideshowImpl::addSlideShowListener( const Reference< XSlideShowListener >& xListener ) 1136 { 1137 if( mxListenerProxy.is() ) 1138 mxListenerProxy->addSlideShowListener( xListener ); 1139 } 1140 1141 void SAL_CALL SlideshowImpl::removeSlideShowListener( const Reference< XSlideShowListener >& xListener ) 1142 { 1143 if( mxListenerProxy.is() ) 1144 mxListenerProxy->removeSlideShowListener( xListener ); 1145 } 1146 1147 void SlideshowImpl::slideEnded(const bool bReverse) 1148 { 1149 if (bReverse) 1150 gotoPreviousSlide(true); 1151 else 1152 gotoNextSlide(); 1153 } 1154 1155 bool SlideshowImpl::swipe(const CommandSwipeData &rSwipeData) 1156 { 1157 if (mbUsePen || mnContextMenuEvent) 1158 return false; 1159 double nVelocityX = rSwipeData.getVelocityX(); 1160 // tdf#108475 make it swipe only if some reasonable movement was involved 1161 if (fabs(nVelocityX) < 50) 1162 return false; 1163 if (nVelocityX > 0) 1164 { 1165 gotoPreviousSlide(); 1166 } 1167 else 1168 { 1169 gotoNextEffect(); 1170 } 1171 //a swipe is followed by a mouse up, tell the view to ignore that mouse up as we've reacted 1172 //to the swipe instead 1173 mxView->ignoreNextMouseReleased(); 1174 return true; 1175 } 1176 1177 bool SlideshowImpl::longpress(const CommandLongPressData &rLongPressData) 1178 { 1179 if (mnContextMenuEvent) 1180 return false; 1181 1182 maPopupMousePos = Point(rLongPressData.getX(), rLongPressData.getY()); 1183 mnContextMenuEvent = Application::PostUserEvent( LINK( this, SlideshowImpl, ContextMenuHdl ) ); 1184 1185 return true; 1186 } 1187 1188 void SlideshowImpl::removeShapeEvents() 1189 { 1190 if( !(mxShow.is() && mxListenerProxy.is()) ) 1191 return; 1192 1193 try 1194 { 1195 for( const auto& rEntry : maShapeEventMap ) 1196 { 1197 mxListenerProxy->removeShapeEventListener( rEntry.first ); 1198 mxShow->setShapeCursor( rEntry.first, awt::SystemPointer::ARROW ); 1199 } 1200 1201 maShapeEventMap.clear(); 1202 } 1203 catch( Exception& ) 1204 { 1205 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::removeShapeEvents()" ); 1206 } 1207 } 1208 1209 void SlideshowImpl::registerShapeEvents(sal_Int32 nSlideNumber) 1210 { 1211 if( nSlideNumber < 0 ) 1212 return; 1213 1214 try 1215 { 1216 Reference< XDrawPagesSupplier > xDrawPages( mxModel, UNO_QUERY_THROW ); 1217 Reference< XIndexAccess > xPages( xDrawPages->getDrawPages(), UNO_QUERY_THROW ); 1218 1219 Reference< XShapes > xDrawPage; 1220 xPages->getByIndex(nSlideNumber) >>= xDrawPage; 1221 1222 if( xDrawPage.is() ) 1223 { 1224 Reference< XMasterPageTarget > xMasterPageTarget( xDrawPage, UNO_QUERY ); 1225 if( xMasterPageTarget.is() ) 1226 { 1227 Reference< XShapes > xMasterPage = xMasterPageTarget->getMasterPage(); 1228 if( xMasterPage.is() ) 1229 registerShapeEvents( xMasterPage ); 1230 } 1231 registerShapeEvents( xDrawPage ); 1232 } 1233 } 1234 catch( Exception& ) 1235 { 1236 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::registerShapeEvents()" ); 1237 } 1238 } 1239 1240 void SlideshowImpl::registerShapeEvents( Reference< XShapes > const & xShapes ) 1241 { 1242 try 1243 { 1244 const sal_Int32 nShapeCount = xShapes->getCount(); 1245 sal_Int32 nShape; 1246 for( nShape = 0; nShape < nShapeCount; nShape++ ) 1247 { 1248 Reference< XShape > xShape; 1249 xShapes->getByIndex( nShape ) >>= xShape; 1250 1251 if( xShape.is() && xShape->getShapeType() == "com.sun.star.drawing.GroupShape" ) 1252 { 1253 Reference< XShapes > xSubShapes( xShape, UNO_QUERY ); 1254 if( xSubShapes.is() ) 1255 registerShapeEvents( xSubShapes ); 1256 } 1257 1258 Reference< XPropertySet > xSet( xShape, UNO_QUERY ); 1259 if( !xSet.is() ) 1260 continue; 1261 1262 Reference< XPropertySetInfo > xSetInfo( xSet->getPropertySetInfo() ); 1263 if( !xSetInfo.is() || !xSetInfo->hasPropertyByName( gsOnClick ) ) 1264 continue; 1265 1266 WrappedShapeEventImplPtr pEvent = std::make_shared<WrappedShapeEventImpl>(); 1267 xSet->getPropertyValue( gsOnClick ) >>= pEvent->meClickAction; 1268 1269 switch( pEvent->meClickAction ) 1270 { 1271 case ClickAction_PREVPAGE: 1272 case ClickAction_NEXTPAGE: 1273 case ClickAction_FIRSTPAGE: 1274 case ClickAction_LASTPAGE: 1275 case ClickAction_STOPPRESENTATION: 1276 break; 1277 case ClickAction_BOOKMARK: 1278 if( xSetInfo->hasPropertyByName( gsBookmark ) ) 1279 xSet->getPropertyValue( gsBookmark ) >>= pEvent->maStrBookmark; 1280 if( getSlideNumberForBookmark( pEvent->maStrBookmark ) == -1 ) 1281 continue; 1282 break; 1283 case ClickAction_DOCUMENT: 1284 case ClickAction_SOUND: 1285 case ClickAction_PROGRAM: 1286 case ClickAction_MACRO: 1287 if( xSetInfo->hasPropertyByName( gsBookmark ) ) 1288 xSet->getPropertyValue( gsBookmark ) >>= pEvent->maStrBookmark; 1289 break; 1290 case ClickAction_VERB: 1291 if( xSetInfo->hasPropertyByName( gsVerb ) ) 1292 xSet->getPropertyValue( gsVerb ) >>= pEvent->mnVerb; 1293 break; 1294 default: 1295 continue; // skip all others 1296 } 1297 1298 maShapeEventMap[ xShape ] = pEvent; 1299 1300 if( mxListenerProxy.is() ) 1301 mxListenerProxy->addShapeEventListener( xShape ); 1302 mxShow->setShapeCursor( xShape, awt::SystemPointer::REFHAND ); 1303 } 1304 } 1305 catch( Exception& ) 1306 { 1307 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::registerShapeEvents()" ); 1308 } 1309 } 1310 1311 void SlideshowImpl::displayCurrentSlide (const bool bSkipAllMainSequenceEffects) 1312 { 1313 stopSound(); 1314 removeShapeEvents(); 1315 1316 if( mpSlideController && mxShow.is() ) 1317 { 1318 Reference< XDrawPagesSupplier > xDrawPages( mpDoc->getUnoModel(), 1319 UNO_QUERY_THROW ); 1320 mpSlideController->displayCurrentSlide( mxShow, xDrawPages, bSkipAllMainSequenceEffects ); 1321 registerShapeEvents(mpSlideController->getCurrentSlideNumber()); 1322 update(); 1323 1324 } 1325 // send out page change event and notify to update all acc info for current page 1326 if (mpViewShell) 1327 { 1328 sal_Int32 currentPageIndex = getCurrentSlideIndex(); 1329 mpViewShell->fireSwitchCurrentPage(currentPageIndex); 1330 mpViewShell->NotifyAccUpdate(); 1331 } 1332 } 1333 1334 void SlideshowImpl::endPresentation() 1335 { 1336 if( maPresSettings.mbMouseAsPen) 1337 { 1338 Reference< XMultiServiceFactory > xDocFactory(mpDoc->getUnoModel(), UNO_QUERY ); 1339 if( xDocFactory.is() ) 1340 mxShow->registerUserPaintPolygons(xDocFactory); 1341 } 1342 1343 if( !mnEndShowEvent ) 1344 mnEndShowEvent = Application::PostUserEvent( LINK(this, SlideshowImpl, endPresentationHdl) ); 1345 } 1346 1347 IMPL_LINK_NOARG(SlideshowImpl, endPresentationHdl, void*, void) 1348 { 1349 mnEndShowEvent = nullptr; 1350 1351 stopSound(); 1352 1353 if( mxPresentation.is() ) 1354 mxPresentation->end(); 1355 } 1356 1357 void SAL_CALL SlideshowImpl::pause() 1358 { 1359 SolarMutexGuard aSolarGuard; 1360 1361 if( mbIsPaused ) 1362 return; 1363 1364 try 1365 { 1366 mbIsPaused = true; 1367 if( mxShow.is() ) 1368 { 1369 mxShow->pause(true); 1370 1371 if( mxListenerProxy.is() ) 1372 mxListenerProxy->paused(); 1373 } 1374 } 1375 catch( Exception& ) 1376 { 1377 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::pause()" ); 1378 } 1379 } 1380 1381 void SAL_CALL SlideshowImpl::resume() 1382 { 1383 SolarMutexGuard aSolarGuard; 1384 1385 if( mbIsPaused ) try 1386 { 1387 if( mpShowWindow->GetShowWindowMode() == SHOWWINDOWMODE_BLANK || mpShowWindow->GetShowWindowMode() == SHOWWINDOWMODE_END ) 1388 { 1389 mpShowWindow->RestartShow(); 1390 } 1391 else 1392 { 1393 mbIsPaused = false; 1394 if( mxShow.is() ) 1395 { 1396 mxShow->pause(false); 1397 update(); 1398 1399 if( mxListenerProxy.is() ) 1400 mxListenerProxy->resumed(); 1401 } 1402 } 1403 } 1404 catch( Exception& ) 1405 { 1406 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::resume()" ); 1407 } 1408 #ifdef ENABLE_SDREMOTE 1409 RemoteServer::presentationStarted( this ); 1410 #endif 1411 } 1412 1413 sal_Bool SAL_CALL SlideshowImpl::isPaused() 1414 { 1415 SolarMutexGuard aSolarGuard; 1416 return mbIsPaused; 1417 } 1418 1419 void SAL_CALL SlideshowImpl::blankScreen( sal_Int32 nColor ) 1420 { 1421 SolarMutexGuard aSolarGuard; 1422 1423 if( mpShowWindow && mpSlideController ) 1424 { 1425 if( mpShowWindow->SetBlankMode( mpSlideController->getCurrentSlideIndex(), Color(ColorTransparency, nColor) ) ) 1426 { 1427 pause(); 1428 } 1429 } 1430 } 1431 1432 // XShapeEventListener 1433 1434 void SlideshowImpl::click( const Reference< XShape >& xShape ) 1435 { 1436 SolarMutexGuard aSolarGuard; 1437 1438 WrappedShapeEventImplPtr pEvent = maShapeEventMap[xShape]; 1439 if( !pEvent ) 1440 return; 1441 1442 switch( pEvent->meClickAction ) 1443 { 1444 case ClickAction_PREVPAGE: gotoPreviousSlide(); break; 1445 case ClickAction_NEXTPAGE: gotoNextSlide(); break; 1446 case ClickAction_FIRSTPAGE: gotoFirstSlide(); break; 1447 case ClickAction_LASTPAGE: gotoLastSlide(); break; 1448 case ClickAction_STOPPRESENTATION: endPresentation(); break; 1449 case ClickAction_BOOKMARK: 1450 { 1451 gotoBookmark( pEvent->maStrBookmark ); 1452 } 1453 break; 1454 case ClickAction_SOUND: 1455 { 1456 #if HAVE_FEATURE_AVMEDIA 1457 try 1458 { 1459 mxPlayer.set(avmedia::MediaWindow::createPlayer(pEvent->maStrBookmark, ""/*TODO?*/), uno::UNO_SET_THROW ); 1460 mxPlayer->start(); 1461 } 1462 catch( uno::Exception& ) 1463 { 1464 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::click()" ); 1465 } 1466 #endif 1467 } 1468 break; 1469 1470 case ClickAction_DOCUMENT: 1471 { 1472 OUString aBookmark( pEvent->maStrBookmark ); 1473 1474 sal_Int32 nPos = aBookmark.indexOf( '#' ); 1475 if( nPos >= 0 ) 1476 { 1477 OUString aURL( aBookmark.copy( 0, nPos+1 ) ); 1478 OUString aName( aBookmark.copy( nPos+1 ) ); 1479 aURL += getUiNameFromPageApiNameImpl( aName ); 1480 aBookmark = aURL; 1481 } 1482 1483 mpDocSh->OpenBookmark( aBookmark ); 1484 } 1485 break; 1486 1487 case ClickAction_PROGRAM: 1488 { 1489 INetURLObject aURL( 1490 ::URIHelper::SmartRel2Abs( 1491 INetURLObject(mpDocSh->GetMedium()->GetBaseURL()), 1492 pEvent->maStrBookmark, ::URIHelper::GetMaybeFileHdl(), true, 1493 false, INetURLObject::EncodeMechanism::WasEncoded, 1494 INetURLObject::DecodeMechanism::Unambiguous ) ); 1495 1496 if( INetProtocol::File == aURL.GetProtocol() ) 1497 { 1498 SfxStringItem aUrl( SID_FILE_NAME, aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); 1499 SfxBoolItem aBrowsing( SID_BROWSE, true ); 1500 1501 SfxViewFrame* pViewFrm = SfxViewFrame::Current(); 1502 if (pViewFrm) 1503 { 1504 SfxUnoFrameItem aDocFrame(SID_FILLFRAME, pViewFrm->GetFrame().GetFrameInterface()); 1505 pViewFrm->GetDispatcher()->ExecuteList( SID_OPENDOC, 1506 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD, 1507 { &aUrl, &aBrowsing }, { &aDocFrame } ); 1508 } 1509 } 1510 } 1511 break; 1512 1513 #if HAVE_FEATURE_SCRIPTING 1514 case presentation::ClickAction_MACRO: 1515 { 1516 const OUString aMacro( pEvent->maStrBookmark ); 1517 1518 if ( SfxApplication::IsXScriptURL( aMacro ) ) 1519 { 1520 Any aRet; 1521 Sequence< sal_Int16 > aOutArgsIndex; 1522 Sequence< Any > aOutArgs; 1523 Sequence< Any >* pInArgs = new Sequence< Any >(0); 1524 mpDocSh->CallXScript( aMacro, *pInArgs, aRet, aOutArgsIndex, aOutArgs); 1525 } 1526 else 1527 { 1528 // aMacro has the following syntax: 1529 // "Macroname.Modulname.Libname.Documentname" or 1530 // "Macroname.Modulname.Libname.Applicationname" 1531 sal_Int32 nIdx{ 0 }; 1532 const std::u16string_view aMacroName = o3tl::getToken(aMacro, 0, '.', nIdx); 1533 const std::u16string_view aModulName = o3tl::getToken(aMacro, 0, '.', nIdx); 1534 1535 // todo: is the limitation still given that only 1536 // Modulname+Macroname can be used here? 1537 OUString aExecMacro = OUString::Concat(aModulName) + "." + aMacroName; 1538 mpDocSh->GetBasic()->Call(aExecMacro); 1539 } 1540 } 1541 break; 1542 #endif 1543 1544 case ClickAction_VERB: 1545 { 1546 // todo, better do it async? 1547 SdrObject* pObj = SdrObject::getSdrObjectFromXShape(xShape); 1548 SdrOle2Obj* pOleObject = dynamic_cast< SdrOle2Obj* >(pObj); 1549 if (pOleObject && mpViewShell ) 1550 mpViewShell->ActivateObject(pOleObject, pEvent->mnVerb); 1551 } 1552 break; 1553 default: 1554 break; 1555 } 1556 } 1557 1558 sal_Int32 SlideshowImpl::getSlideNumberForBookmark( const OUString& rStrBookmark ) 1559 { 1560 bool bIsMasterPage; 1561 OUString aBookmark = getUiNameFromPageApiNameImpl( rStrBookmark ); 1562 sal_uInt16 nPgNum = mpDoc->GetPageByName( aBookmark, bIsMasterPage ); 1563 1564 if( nPgNum == SDRPAGE_NOTFOUND ) 1565 { 1566 // Is the bookmark an object? 1567 SdrObject* pObj = mpDoc->GetObj( aBookmark ); 1568 1569 if( pObj ) 1570 { 1571 nPgNum = pObj->getSdrPageFromSdrObject()->GetPageNum(); 1572 bIsMasterPage = pObj->getSdrPageFromSdrObject()->IsMasterPage(); 1573 } 1574 } 1575 1576 if( (nPgNum == SDRPAGE_NOTFOUND) || bIsMasterPage || static_cast<SdPage*>(mpDoc->GetPage(nPgNum))->GetPageKind() != PageKind::Standard ) 1577 return -1; 1578 1579 return ( nPgNum - 1) >> 1; 1580 } 1581 1582 void SlideshowImpl::hyperLinkClicked( OUString const& aHyperLink ) 1583 { 1584 OUString aBookmark( aHyperLink ); 1585 1586 sal_Int32 nPos = aBookmark.indexOf( '#' ); 1587 if( nPos >= 0 ) 1588 { 1589 OUString aURL( aBookmark.copy( 0, nPos+1 ) ); 1590 OUString aName( aBookmark.copy( nPos+1 ) ); 1591 aURL += getUiNameFromPageApiNameImpl( aName ); 1592 aBookmark = aURL; 1593 } 1594 1595 mpDocSh->OpenBookmark( aBookmark ); 1596 } 1597 1598 void SlideshowImpl::displaySlideNumber( sal_Int32 nSlideNumber ) 1599 { 1600 if( mpSlideController ) 1601 { 1602 if( mpSlideController->jumpToSlideNumber( nSlideNumber ) ) 1603 { 1604 displayCurrentSlide(); 1605 } 1606 } 1607 } 1608 1609 /** nSlideIndex == -1 displays current slide again */ 1610 void SlideshowImpl::displaySlideIndex( sal_Int32 nSlideIndex ) 1611 { 1612 if( mpSlideController ) 1613 { 1614 if( (nSlideIndex == -1) || mpSlideController->jumpToSlideIndex( nSlideIndex ) ) 1615 { 1616 displayCurrentSlide(); 1617 } 1618 } 1619 } 1620 1621 void SlideshowImpl::jumpToBookmark( const OUString& sBookmark ) 1622 { 1623 sal_Int32 nSlideNumber = getSlideNumberForBookmark( sBookmark ); 1624 if( nSlideNumber != -1 ) 1625 displaySlideNumber( nSlideNumber ); 1626 } 1627 1628 sal_Int32 SlideshowImpl::getCurrentSlideNumber() const 1629 { 1630 return mpSlideController ? mpSlideController->getCurrentSlideNumber() : -1; 1631 } 1632 1633 sal_Bool SAL_CALL SlideshowImpl::isEndless() 1634 { 1635 SolarMutexGuard aSolarGuard; 1636 return maPresSettings.mbEndless; 1637 } 1638 1639 void SlideshowImpl::update() 1640 { 1641 startUpdateTimer(); 1642 } 1643 1644 void SlideshowImpl::startUpdateTimer() 1645 { 1646 SolarMutexGuard aSolarGuard; 1647 maUpdateTimer.SetTimeout( 0 ); 1648 maUpdateTimer.Start(); 1649 } 1650 1651 /** this timer is called 20ms after a new slide was displayed. 1652 This is used to unfreeze user input that was disabled after 1653 slide change to skip input that was buffered during slide 1654 transition preparation */ 1655 IMPL_LINK_NOARG(SlideshowImpl, ReadyForNextInputHdl, Timer *, void) 1656 { 1657 mbInputFreeze = false; 1658 } 1659 1660 /** if I catch someone someday who calls this method by hand 1661 and not by using the timer, I will personally punish this 1662 person seriously, even if this person is me. 1663 */ 1664 IMPL_LINK_NOARG(SlideshowImpl, updateHdl, Timer *, void) 1665 { 1666 updateSlideShow(); 1667 } 1668 1669 void SlideshowImpl::updateSlideShow() 1670 { 1671 // prevent me from deletion when recursing (App::EnableYieldMode does) 1672 const rtl::Reference<SlideshowImpl> xKeepAlive(this); 1673 1674 Reference< XSlideShow > xShow( mxShow ); 1675 if ( ! xShow.is()) 1676 return; 1677 1678 try 1679 { 1680 double fUpdate = 0.0; 1681 if( !xShow->update(fUpdate) ) 1682 fUpdate = -1.0; 1683 1684 if (mxShow.is() && (fUpdate >= 0.0)) 1685 { 1686 if (::basegfx::fTools::equalZero(fUpdate)) 1687 { 1688 // Make sure idle tasks don't starve when we don't have to wait. 1689 // Don't process any events generated after invoking the function. 1690 Application::Reschedule(/*bHandleAllCurrentEvents=*/true); 1691 } 1692 else 1693 { 1694 // Avoid busy loop when the previous call to update() 1695 // returns a small positive number but not 0 (which is 1696 // handled above). Also, make sure that calls to update() 1697 // have a minimum frequency. 1698 // => Allow up to 60 frames per second. Call at least once 1699 // every 4 seconds. 1700 const static sal_Int32 nMaximumFrameCount (60); 1701 const static double nMinimumTimeout (1.0 / nMaximumFrameCount); 1702 const static double nMaximumTimeout (4.0); 1703 fUpdate = std::clamp(fUpdate, nMinimumTimeout, nMaximumTimeout); 1704 1705 // Make sure that the maximum frame count has not been set 1706 // too high (only then conversion to milliseconds and long 1707 // integer may lead to zero value.) 1708 OSL_ASSERT(static_cast<sal_uLong>(fUpdate * 1000.0) > 0); 1709 } 1710 1711 // Use our high resolution timers for the asynchronous callback. 1712 maUpdateTimer.SetTimeout(static_cast<sal_uLong>(fUpdate * 1000.0)); 1713 maUpdateTimer.Start(); 1714 } 1715 } 1716 catch( Exception& ) 1717 { 1718 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::updateSlideShow()" ); 1719 } 1720 } 1721 1722 bool SlideshowImpl::keyInput(const KeyEvent& rKEvt) 1723 { 1724 if( !mxShow.is() || mbInputFreeze ) 1725 return false; 1726 1727 bool bRet = true; 1728 1729 try 1730 { 1731 const int nKeyCode = rKEvt.GetKeyCode().GetCode(); 1732 switch( nKeyCode ) 1733 { 1734 case awt::Key::CONTEXTMENU: 1735 if( !mnContextMenuEvent ) 1736 { 1737 if( mpShowWindow ) 1738 maPopupMousePos = mpShowWindow->GetPointerState().maPos; 1739 mnContextMenuEvent = Application::PostUserEvent( LINK( this, SlideshowImpl, ContextMenuHdl ) ); 1740 } 1741 break; 1742 1743 // cancel show 1744 case KEY_ESCAPE: 1745 case KEY_SUBTRACT: 1746 // in case the user cancels the presentation, switch to current slide 1747 // in edit mode 1748 if( mpSlideController && (ANIMATIONMODE_SHOW == meAnimationMode) ) 1749 { 1750 if( mpSlideController->getCurrentSlideNumber() != -1 ) 1751 mnRestoreSlide = mpSlideController->getCurrentSlideNumber(); 1752 } 1753 endPresentation(); 1754 break; 1755 1756 // advance show 1757 case KEY_PAGEDOWN: 1758 if(rKEvt.GetKeyCode().IsMod2()) 1759 { 1760 gotoNextSlide(); 1761 break; 1762 } 1763 [[fallthrough]]; 1764 case KEY_SPACE: 1765 case KEY_RIGHT: 1766 case KEY_DOWN: 1767 gotoNextEffect(); 1768 break; 1769 1770 case KEY_RETURN: 1771 { 1772 if( !maCharBuffer.isEmpty() ) 1773 { 1774 if( mpSlideController ) 1775 { 1776 if( mpSlideController->jumpToSlideNumber( maCharBuffer.toInt32() - 1 ) ) 1777 displayCurrentSlide(); 1778 } 1779 maCharBuffer.clear(); 1780 } 1781 else 1782 { 1783 gotoNextEffect(); 1784 } 1785 } 1786 break; 1787 1788 // numeric: add to buffer 1789 case KEY_0: 1790 case KEY_1: 1791 case KEY_2: 1792 case KEY_3: 1793 case KEY_4: 1794 case KEY_5: 1795 case KEY_6: 1796 case KEY_7: 1797 case KEY_8: 1798 case KEY_9: 1799 maCharBuffer += OUStringChar( rKEvt.GetCharCode() ); 1800 break; 1801 1802 case KEY_PAGEUP: 1803 if(rKEvt.GetKeyCode().IsMod2()) 1804 { 1805 gotoPreviousSlide(); 1806 break; 1807 } 1808 [[fallthrough]]; 1809 case KEY_LEFT: 1810 case KEY_UP: 1811 case KEY_BACKSPACE: 1812 gotoPreviousEffect(); 1813 break; 1814 1815 case KEY_P: 1816 setUsePen( !mbUsePen ); 1817 break; 1818 1819 case KEY_E: 1820 setEraseAllInk( true ); 1821 updateSlideShow(); 1822 break; 1823 1824 case KEY_HOME: 1825 gotoFirstSlide(); 1826 break; 1827 1828 case KEY_END: 1829 gotoLastSlide(); 1830 break; 1831 1832 case KEY_B: 1833 case KEY_W: 1834 case KEY_POINT: 1835 case KEY_COMMA: 1836 { 1837 blankScreen( ((nKeyCode == KEY_W ) || (nKeyCode == KEY_COMMA)) ? 0x00ffffff : 0x00000000 ); 1838 } 1839 break; 1840 1841 default: 1842 bRet = false; 1843 break; 1844 } 1845 } 1846 catch( Exception& ) 1847 { 1848 bRet = false; 1849 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::keyInput()" ); 1850 } 1851 1852 return bRet; 1853 } 1854 1855 IMPL_LINK( SlideshowImpl, EventListenerHdl, VclSimpleEvent&, rSimpleEvent, void ) 1856 { 1857 if( !mxShow.is() || mbInputFreeze ) 1858 return; 1859 1860 if( !((rSimpleEvent.GetId() == VclEventId::WindowCommand) && static_cast<VclWindowEvent*>(&rSimpleEvent)->GetData()) ) 1861 return; 1862 1863 const CommandEvent& rEvent = *static_cast<const CommandEvent*>(static_cast<VclWindowEvent*>(&rSimpleEvent)->GetData()); 1864 1865 if( rEvent.GetCommand() != CommandEventId::Media ) 1866 return; 1867 1868 CommandMediaData* pMediaData = rEvent.GetMediaData(); 1869 pMediaData->SetPassThroughToOS(false); 1870 switch (pMediaData->GetMediaId()) 1871 { 1872 #if defined( MACOSX ) 1873 case MediaCommand::Menu: 1874 if( !mnContextMenuEvent ) 1875 { 1876 if( mpShowWindow ) 1877 maPopupMousePos = mpShowWindow->GetPointerState().maPos; 1878 mnContextMenuEvent = Application::PostUserEvent( LINK( this, SlideshowImpl, ContextMenuHdl ) ); 1879 } 1880 break; 1881 case MediaCommand::VolumeDown: 1882 gotoPreviousSlide(); 1883 break; 1884 case MediaCommand::VolumeUp: 1885 gotoNextEffect(); 1886 break; 1887 #endif 1888 case MediaCommand::NextTrack: 1889 gotoNextEffect(); 1890 break; 1891 case MediaCommand::Pause: 1892 if( !mbIsPaused ) 1893 blankScreen(0); 1894 break; 1895 case MediaCommand::Play: 1896 if( mbIsPaused ) 1897 resume(); 1898 break; 1899 1900 case MediaCommand::PlayPause: 1901 if( mbIsPaused ) 1902 resume(); 1903 else 1904 blankScreen(0); 1905 break; 1906 case MediaCommand::PreviousTrack: 1907 gotoPreviousSlide(); 1908 break; 1909 case MediaCommand::NextTrackHold: 1910 gotoLastSlide(); 1911 break; 1912 1913 case MediaCommand::Rewind: 1914 gotoFirstSlide(); 1915 break; 1916 case MediaCommand::Stop: 1917 // in case the user cancels the presentation, switch to current slide 1918 // in edit mode 1919 if( mpSlideController && (ANIMATIONMODE_SHOW == meAnimationMode) ) 1920 { 1921 if( mpSlideController->getCurrentSlideNumber() != -1 ) 1922 mnRestoreSlide = mpSlideController->getCurrentSlideNumber(); 1923 } 1924 endPresentation(); 1925 break; 1926 default: 1927 pMediaData->SetPassThroughToOS(true); 1928 break; 1929 } 1930 } 1931 1932 void SlideshowImpl::mouseButtonUp(const MouseEvent& rMEvt) 1933 { 1934 if( rMEvt.IsRight() && !mnContextMenuEvent ) 1935 { 1936 maPopupMousePos = rMEvt.GetPosPixel(); 1937 mnContextMenuEvent = Application::PostUserEvent( LINK( this, SlideshowImpl, ContextMenuHdl ) ); 1938 } 1939 } 1940 1941 IMPL_LINK_NOARG(SlideshowImpl, ContextMenuHdl, void*, void) 1942 { 1943 mnContextMenuEvent = nullptr; 1944 1945 if (mpSlideController == nullptr) 1946 return; 1947 1948 mbWasPaused = mbIsPaused; 1949 if( !mbWasPaused ) 1950 pause(); 1951 1952 std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(nullptr, "modules/simpress/ui/slidecontextmenu.ui")); 1953 std::unique_ptr<weld::Menu> xMenu(xBuilder->weld_menu("menu")); 1954 OUString sNextImage(BMP_MENU_NEXT), sPrevImage(BMP_MENU_PREV); 1955 xMenu->insert(0, "next", SdResId(RID_SVXSTR_MENU_NEXT), &sNextImage, nullptr, nullptr, TRISTATE_INDET); 1956 xMenu->insert(1, "prev", SdResId(RID_SVXSTR_MENU_PREV), &sPrevImage, nullptr, nullptr, TRISTATE_INDET); 1957 1958 // Adding button to display if in Pen mode 1959 xMenu->set_active("pen", mbUsePen); 1960 1961 const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode(); 1962 xMenu->set_visible("next", mpSlideController->getNextSlideIndex() != -1); 1963 xMenu->set_visible("prev", (mpSlideController->getPreviousSlideIndex() != -1 ) || (eMode == SHOWWINDOWMODE_END) || (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK)); 1964 xMenu->set_visible("edit", mpViewShell->GetDoc()->IsStartWithPresentation()); 1965 1966 std::unique_ptr<weld::Menu> xPageMenu(xBuilder->weld_menu("gotomenu")); 1967 OUString sFirstImage(BMP_MENU_FIRST), sLastImage(BMP_MENU_LAST); 1968 xPageMenu->insert(0, "first", SdResId(RID_SVXSTR_MENU_FIRST), &sFirstImage, nullptr, nullptr, TRISTATE_INDET); 1969 xPageMenu->insert(1, "last", SdResId(RID_SVXSTR_MENU_LAST), &sLastImage, nullptr, nullptr, TRISTATE_INDET); 1970 1971 // populate slide goto list 1972 const sal_Int32 nPageNumberCount = mpSlideController->getSlideNumberCount(); 1973 if( nPageNumberCount <= 1 ) 1974 { 1975 xMenu->set_visible("goto", false); 1976 } 1977 else 1978 { 1979 sal_Int32 nCurrentSlideNumber = mpSlideController->getCurrentSlideNumber(); 1980 if( (eMode == SHOWWINDOWMODE_END) || (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) ) 1981 nCurrentSlideNumber = -1; 1982 1983 xPageMenu->set_visible("first", mpSlideController->getSlideNumber(0) != nCurrentSlideNumber); 1984 xPageMenu->set_visible("last", mpSlideController->getSlideNumber(mpSlideController->getSlideIndexCount() - 1) != nCurrentSlideNumber); 1985 1986 sal_Int32 nPageNumber; 1987 1988 for( nPageNumber = 0; nPageNumber < nPageNumberCount; nPageNumber++ ) 1989 { 1990 if( mpSlideController->isVisibleSlideNumber( nPageNumber ) ) 1991 { 1992 SdPage* pPage = mpDoc->GetSdPage(static_cast<sal_uInt16>(nPageNumber), PageKind::Standard); 1993 if (pPage) 1994 { 1995 OUString sId(OUString::number(CM_SLIDES + nPageNumber)); 1996 xPageMenu->append_check(sId, pPage->GetName()); 1997 if (nPageNumber == nCurrentSlideNumber) 1998 xPageMenu->set_active(sId.toUtf8(), true); 1999 } 2000 } 2001 } 2002 } 2003 2004 std::unique_ptr<weld::Menu> xBlankMenu(xBuilder->weld_menu("screenmenu")); 2005 2006 if (mpShowWindow->GetShowWindowMode() == SHOWWINDOWMODE_BLANK) 2007 { 2008 xBlankMenu->set_active((mpShowWindow->GetBlankColor() == COL_WHITE) ? "white" : "black", true); 2009 } 2010 2011 std::unique_ptr<weld::Menu> xWidthMenu(xBuilder->weld_menu("widthmenu")); 2012 2013 // populate color width list 2014 sal_Int32 nIterator; 2015 double nWidth; 2016 2017 nWidth = 4.0; 2018 for( nIterator = 1; nIterator < 6; nIterator++) 2019 { 2020 switch(nIterator) 2021 { 2022 case 1: 2023 nWidth = 4.0; 2024 break; 2025 case 2: 2026 nWidth = 100.0; 2027 break; 2028 case 3: 2029 nWidth = 150.0; 2030 break; 2031 case 4: 2032 nWidth = 200.0; 2033 break; 2034 case 5: 2035 nWidth = 400.0; 2036 break; 2037 default: 2038 break; 2039 } 2040 2041 if (nWidth == mdUserPaintStrokeWidth) 2042 xWidthMenu->set_active(OString::number(nWidth), true); 2043 } 2044 2045 ::tools::Rectangle aRect(maPopupMousePos, Size(1,1)); 2046 weld::Window* pParent = weld::GetPopupParent(*mpShowWindow, aRect); 2047 ContextMenuSelectHdl(xMenu->popup_at_rect(pParent, aRect)); 2048 2049 if( mxView.is() ) 2050 mxView->ignoreNextMouseReleased(); 2051 2052 if( !mbWasPaused ) 2053 resume(); 2054 } 2055 2056 void SlideshowImpl::ContextMenuSelectHdl(std::string_view rMenuId) 2057 { 2058 if (rMenuId == "prev") 2059 { 2060 gotoPreviousSlide(); 2061 mbWasPaused = false; 2062 } 2063 else if(rMenuId == "next") 2064 { 2065 gotoNextSlide(); 2066 mbWasPaused = false; 2067 } 2068 else if (rMenuId == "first") 2069 { 2070 gotoFirstSlide(); 2071 mbWasPaused = false; 2072 } 2073 else if (rMenuId == "last") 2074 { 2075 gotoLastSlide(); 2076 mbWasPaused = false; 2077 } 2078 else if (rMenuId == "black" || rMenuId == "white") 2079 { 2080 const Color aBlankColor(rMenuId == "white" ? COL_WHITE : COL_BLACK); 2081 if( mbWasPaused ) 2082 { 2083 if( mpShowWindow->GetShowWindowMode() == SHOWWINDOWMODE_BLANK ) 2084 { 2085 if( mpShowWindow->GetBlankColor() == aBlankColor ) 2086 { 2087 mbWasPaused = false; 2088 mpShowWindow->RestartShow(); 2089 return; 2090 } 2091 } 2092 mpShowWindow->RestartShow(); 2093 } 2094 if( mpShowWindow->SetBlankMode( mpSlideController->getCurrentSlideIndex(), aBlankColor ) ) 2095 { 2096 pause(); 2097 mbWasPaused = true; 2098 } 2099 } 2100 else if (rMenuId == "color") 2101 { 2102 //Open a color picker based on SvColorDialog 2103 ::Color aColor( ColorTransparency, mnUserPaintColor ); 2104 SvColorDialog aColorDlg; 2105 aColorDlg.SetColor( aColor ); 2106 2107 if (aColorDlg.Execute(mpShowWindow->GetFrameWeld())) 2108 { 2109 aColor = aColorDlg.GetColor(); 2110 setPenColor(sal_Int32(aColor)); 2111 } 2112 mbWasPaused = false; 2113 } 2114 else if (rMenuId == "4") 2115 { 2116 setPenWidth(4.0); 2117 mbWasPaused = false; 2118 } 2119 else if (rMenuId == "100") 2120 { 2121 setPenWidth(100.0); 2122 mbWasPaused = false; 2123 } 2124 else if (rMenuId == "150") 2125 { 2126 setPenWidth(150.0); 2127 mbWasPaused = false; 2128 } 2129 else if (rMenuId == "200") 2130 { 2131 setPenWidth(200.0); 2132 mbWasPaused = false; 2133 } 2134 else if (rMenuId == "400") 2135 { 2136 setPenWidth(400.0); 2137 mbWasPaused = false; 2138 } 2139 else if (rMenuId == "erase") 2140 { 2141 setEraseAllInk(true); 2142 mbWasPaused = false; 2143 } 2144 else if (rMenuId == "pen") 2145 { 2146 setUsePen(!mbUsePen); 2147 mbWasPaused = false; 2148 } 2149 else if (rMenuId == "edit") 2150 { 2151 // When in autoplay mode (pps/ppsx), offer editing of the presentation 2152 // Turn autostart off, else Impress will close when exiting the Presentation 2153 mpViewShell->GetDoc()->SetExitAfterPresenting(false); 2154 if( mpSlideController && (ANIMATIONMODE_SHOW == meAnimationMode) ) 2155 { 2156 if( mpSlideController->getCurrentSlideNumber() != -1 ) 2157 { 2158 mnRestoreSlide = mpSlideController->getCurrentSlideNumber(); 2159 } 2160 } 2161 endPresentation(); 2162 } 2163 else if (rMenuId == "end") 2164 { 2165 // in case the user cancels the presentation, switch to current slide 2166 // in edit mode 2167 if( mpSlideController && (ANIMATIONMODE_SHOW == meAnimationMode) ) 2168 { 2169 if( mpSlideController->getCurrentSlideNumber() != -1 ) 2170 { 2171 mnRestoreSlide = mpSlideController->getCurrentSlideNumber(); 2172 } 2173 } 2174 endPresentation(); 2175 } 2176 else if (!rMenuId.empty()) 2177 { 2178 sal_Int32 nPageNumber = o3tl::toInt32(rMenuId) - CM_SLIDES; 2179 const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode(); 2180 if( (eMode == SHOWWINDOWMODE_END) || (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) ) 2181 { 2182 mpShowWindow->RestartShow( nPageNumber ); 2183 } 2184 else if( nPageNumber != mpSlideController->getCurrentSlideNumber() ) 2185 { 2186 displaySlideNumber( nPageNumber ); 2187 } 2188 mbWasPaused = false; 2189 } 2190 } 2191 2192 Reference< XSlideShow > SlideshowImpl::createSlideShow() 2193 { 2194 Reference< XSlideShow > xShow; 2195 2196 try 2197 { 2198 Reference< uno::XComponentContext > xContext = 2199 ::comphelper::getProcessComponentContext(); 2200 2201 xShow.set( presentation::SlideShow::create(xContext), UNO_SET_THROW ); 2202 } 2203 catch( uno::Exception& ) 2204 { 2205 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::createSlideShow()" ); 2206 } 2207 2208 return xShow; 2209 } 2210 2211 void SlideshowImpl::createSlideList( bool bAll, std::u16string_view rPresSlide ) 2212 { 2213 const sal_uInt16 nSlideCount = mpDoc->GetSdPageCount( PageKind::Standard ); 2214 2215 if( !nSlideCount ) 2216 return; 2217 2218 SdCustomShow* pCustomShow; 2219 2220 if( mpDoc->GetCustomShowList() && maPresSettings.mbCustomShow ) 2221 pCustomShow = mpDoc->GetCustomShowList()->GetCurObject(); 2222 else 2223 pCustomShow = nullptr; 2224 2225 // create animation slide controller 2226 AnimationSlideController::Mode eMode = 2227 ( pCustomShow && !pCustomShow->PagesVector().empty() ) ? AnimationSlideController::CUSTOM : 2228 (bAll ? AnimationSlideController::ALL : AnimationSlideController::FROM); 2229 2230 Reference< XDrawPagesSupplier > xDrawPages( mpDoc->getUnoModel(), UNO_QUERY_THROW ); 2231 Reference< XIndexAccess > xSlides( xDrawPages->getDrawPages(), UNO_QUERY_THROW ); 2232 mpSlideController = std::make_shared<AnimationSlideController>( xSlides, eMode ); 2233 2234 if( eMode != AnimationSlideController::CUSTOM ) 2235 { 2236 sal_Int32 nFirstVisibleSlide = 0; 2237 2238 // normal presentation 2239 if( !rPresSlide.empty() ) 2240 { 2241 sal_Int32 nSlide; 2242 bool bTakeNextAvailable = false; 2243 2244 for( nSlide = 0, nFirstVisibleSlide = -1; 2245 ( nSlide < nSlideCount ) && ( -1 == nFirstVisibleSlide ); nSlide++ ) 2246 { 2247 SdPage* pTestSlide = mpDoc->GetSdPage( static_cast<sal_uInt16>(nSlide), PageKind::Standard ); 2248 2249 if( pTestSlide->GetName() == rPresSlide ) 2250 { 2251 if( pTestSlide->IsExcluded() ) 2252 bTakeNextAvailable = true; 2253 else 2254 nFirstVisibleSlide = nSlide; 2255 } 2256 else if( bTakeNextAvailable && !pTestSlide->IsExcluded() ) 2257 nFirstVisibleSlide = nSlide; 2258 } 2259 2260 if( -1 == nFirstVisibleSlide ) 2261 nFirstVisibleSlide = 0; 2262 } 2263 2264 for( sal_Int32 i = 0; i < nSlideCount; i++ ) 2265 { 2266 bool bVisible = ! mpDoc->GetSdPage( static_cast<sal_uInt16>(i), PageKind::Standard )->IsExcluded(); 2267 if( bVisible || (eMode == AnimationSlideController::ALL) ) 2268 mpSlideController->insertSlideNumber( i, bVisible ); 2269 } 2270 2271 mpSlideController->setStartSlideNumber( nFirstVisibleSlide ); 2272 } 2273 else 2274 { 2275 if( meAnimationMode != ANIMATIONMODE_SHOW && !rPresSlide.empty() ) 2276 { 2277 sal_Int32 nSlide; 2278 for( nSlide = 0; nSlide < nSlideCount; nSlide++ ) 2279 if( rPresSlide == mpDoc->GetSdPage( static_cast<sal_uInt16>(nSlide), PageKind::Standard )->GetName() ) 2280 break; 2281 2282 if( nSlide < nSlideCount ) 2283 mpSlideController->insertSlideNumber( static_cast<sal_uInt16>(nSlide) ); 2284 } 2285 2286 for( const auto& rpPage : pCustomShow->PagesVector() ) 2287 { 2288 const sal_uInt16 nSdSlide = ( rpPage->GetPageNum() - 1 ) / 2; 2289 2290 if( ! mpDoc->GetSdPage( nSdSlide, PageKind::Standard )->IsExcluded()) 2291 mpSlideController->insertSlideNumber( nSdSlide ); 2292 } 2293 } 2294 } 2295 2296 typedef sal_uInt16 (*FncGetChildWindowId)(); 2297 2298 const FncGetChildWindowId aShowChildren[] = 2299 { 2300 &AnimationChildWindow::GetChildWindowId, 2301 &Svx3DChildWindow::GetChildWindowId, 2302 &SvxFontWorkChildWindow::GetChildWindowId, 2303 &SvxColorChildWindow::GetChildWindowId, 2304 &SvxSearchDialogWrapper::GetChildWindowId, 2305 &SvxBmpMaskChildWindow::GetChildWindowId, 2306 &SvxIMapDlgChildWindow::GetChildWindowId, 2307 &SvxHlinkDlgWrapper::GetChildWindowId, 2308 &SfxInfoBarContainerChild::GetChildWindowId 2309 }; 2310 2311 void SlideshowImpl::hideChildWindows() 2312 { 2313 mnChildMask = 0; 2314 2315 if( ANIMATIONMODE_SHOW != meAnimationMode ) 2316 return; 2317 2318 SfxViewFrame* pViewFrame = getViewFrame(); 2319 2320 if( !pViewFrame ) 2321 return; 2322 2323 for( sal_uLong i = 0; i < SAL_N_ELEMENTS( aShowChildren ); i++ ) 2324 { 2325 const sal_uInt16 nId = ( *aShowChildren[ i ] )(); 2326 2327 if( pViewFrame->GetChildWindow( nId ) ) 2328 { 2329 pViewFrame->SetChildWindow( nId, false ); 2330 mnChildMask |= ::tools::ULong(1) << i; 2331 } 2332 } 2333 } 2334 2335 void SlideshowImpl::showChildWindows() 2336 { 2337 if( ANIMATIONMODE_SHOW == meAnimationMode ) 2338 { 2339 SfxViewFrame* pViewFrame = getViewFrame(); 2340 if( pViewFrame ) 2341 { 2342 for( sal_uLong i = 0; i < SAL_N_ELEMENTS(aShowChildren); i++ ) 2343 { 2344 if( mnChildMask & ( ::tools::ULong(1) << i ) ) 2345 pViewFrame->SetChildWindow( ( *aShowChildren[ i ] )(), true ); 2346 } 2347 } 2348 } 2349 } 2350 2351 SfxViewFrame* SlideshowImpl::getViewFrame() const 2352 { 2353 return mpViewShell ? mpViewShell->GetViewFrame() : nullptr; 2354 } 2355 2356 SfxDispatcher* SlideshowImpl::getDispatcher() const 2357 { 2358 return (mpViewShell && mpViewShell->GetViewFrame()) ? mpViewShell->GetViewFrame()->GetDispatcher() : nullptr; 2359 } 2360 2361 SfxBindings* SlideshowImpl::getBindings() const 2362 { 2363 return (mpViewShell && mpViewShell->GetViewFrame()) ? &mpViewShell->GetViewFrame()->GetBindings() : nullptr; 2364 } 2365 2366 void SlideshowImpl::resize( const Size& rSize ) 2367 { 2368 maPresSize = rSize; 2369 2370 if(mpShowWindow) 2371 { 2372 mpShowWindow->SetSizePixel( maPresSize ); 2373 mpShowWindow->Show(); 2374 } 2375 2376 if( mxView.is() ) try 2377 { 2378 awt::WindowEvent aEvt; 2379 mxView->windowResized(aEvt); 2380 } 2381 catch( Exception& ) 2382 { 2383 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::resize()" ); 2384 } 2385 } 2386 2387 void SlideshowImpl::setActiveXToolbarsVisible( bool bVisible ) 2388 { 2389 // in case of ActiveX control the toolbars should not be visible if slide show runs in window mode 2390 // actually it runs always in window mode in case of ActiveX control 2391 if ( !(!maPresSettings.mbFullScreen && mpDocSh && mpDocSh->GetMedium()) ) 2392 return; 2393 2394 const SfxBoolItem* pItem = SfxItemSet::GetItem<SfxBoolItem>(mpDocSh->GetMedium()->GetItemSet(), SID_VIEWONLY, false); 2395 if ( !(pItem && pItem->GetValue()) ) 2396 return; 2397 2398 // this is a plugin/activex mode, no toolbars should be visible during slide show 2399 // after the end of slide show they should be visible again 2400 SfxViewFrame* pViewFrame = getViewFrame(); 2401 if( !pViewFrame ) 2402 return; 2403 2404 try 2405 { 2406 Reference< frame::XLayoutManager > xLayoutManager; 2407 Reference< beans::XPropertySet > xFrameProps( pViewFrame->GetFrame().GetFrameInterface(), UNO_QUERY_THROW ); 2408 if ( ( xFrameProps->getPropertyValue( "LayoutManager" ) 2409 >>= xLayoutManager ) 2410 && xLayoutManager.is() ) 2411 { 2412 xLayoutManager->setVisible( bVisible ); 2413 } 2414 } 2415 catch( uno::Exception& ) 2416 {} 2417 } 2418 2419 void SAL_CALL SlideshowImpl::activate() 2420 { 2421 SolarMutexGuard aSolarGuard; 2422 2423 maDeactivateTimer.Stop(); 2424 2425 if( mbActive || !mxShow.is() ) 2426 return; 2427 2428 mbActive = true; 2429 2430 if( ANIMATIONMODE_SHOW == meAnimationMode ) 2431 { 2432 if( mbAutoSaveWasOn ) 2433 setAutoSaveState( false ); 2434 2435 if( mpShowWindow ) 2436 { 2437 SfxViewFrame* pViewFrame = getViewFrame(); 2438 SfxDispatcher* pDispatcher = pViewFrame ? pViewFrame->GetDispatcher() : nullptr; 2439 2440 hideChildWindows(); 2441 2442 if( pDispatcher ) 2443 { 2444 // filter all forbidden slots 2445 pDispatcher->SetSlotFilter( SfxSlotFilterState::ENABLED, pAllowed ); 2446 } 2447 2448 if( getBindings() ) 2449 getBindings()->InvalidateAll(true); 2450 2451 mpShowWindow->GrabFocus(); 2452 } 2453 } 2454 2455 resume(); 2456 } 2457 2458 void SAL_CALL SlideshowImpl::deactivate() 2459 { 2460 SolarMutexGuard aSolarGuard; 2461 2462 if( mbActive && mxShow.is() ) 2463 { 2464 maDeactivateTimer.Start(); 2465 } 2466 } 2467 2468 IMPL_LINK_NOARG(SlideshowImpl, deactivateHdl, Timer *, void) 2469 { 2470 if( !(mbActive && mxShow.is()) ) 2471 return; 2472 2473 mbActive = false; 2474 2475 pause(); 2476 2477 if( ANIMATIONMODE_SHOW == meAnimationMode ) 2478 { 2479 if( mbAutoSaveWasOn ) 2480 setAutoSaveState( true ); 2481 2482 if( mpShowWindow ) 2483 { 2484 showChildWindows(); 2485 } 2486 } 2487 } 2488 2489 sal_Bool SAL_CALL SlideshowImpl::isActive() 2490 { 2491 SolarMutexGuard aSolarGuard; 2492 return mbActive; 2493 } 2494 2495 void SlideshowImpl::setAutoSaveState( bool bOn) 2496 { 2497 try 2498 { 2499 uno::Reference<uno::XComponentContext> xContext( ::comphelper::getProcessComponentContext() ); 2500 2501 uno::Reference< util::XURLTransformer > xParser(util::URLTransformer::create(xContext)); 2502 util::URL aURL; 2503 aURL.Complete = "vnd.sun.star.autorecovery:/setAutoSaveState"; 2504 xParser->parseStrict(aURL); 2505 2506 Sequence< beans::PropertyValue > aArgs{ comphelper::makePropertyValue("AutoSaveState", 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 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 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 2546 sal_Int32 SAL_CALL SlideshowImpl::getCurrentSlideIndex() 2547 { 2548 return mpSlideController ? mpSlideController->getCurrentSlideIndex() : -1; 2549 } 2550 2551 // css::presentation::XSlideShowController: 2552 2553 ::sal_Int32 SAL_CALL SlideshowImpl::getSlideCount() 2554 { 2555 return mpSlideController ? mpSlideController->getSlideIndexCount() : 0; 2556 } 2557 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 2567 sal_Bool SAL_CALL SlideshowImpl::getAlwaysOnTop() 2568 { 2569 SolarMutexGuard aSolarGuard; 2570 return maPresSettings.mbAlwaysOnTop; 2571 } 2572 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 2583 sal_Bool SAL_CALL SlideshowImpl::isFullScreen() 2584 { 2585 SolarMutexGuard aSolarGuard; 2586 return maPresSettings.mbFullScreen; 2587 } 2588 2589 sal_Bool SAL_CALL SlideshowImpl::getMouseVisible() 2590 { 2591 SolarMutexGuard aSolarGuard; 2592 return maPresSettings.mbMouseVisible; 2593 } 2594 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 2606 sal_Bool SAL_CALL SlideshowImpl::getUsePen() 2607 { 2608 SolarMutexGuard aSolarGuard; 2609 return mbUsePen; 2610 } 2611 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 2651 double SAL_CALL SlideshowImpl::getPenWidth() 2652 { 2653 SolarMutexGuard aSolarGuard; 2654 return mdUserPaintStrokeWidth; 2655 } 2656 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 2664 sal_Int32 SAL_CALL SlideshowImpl::getPenColor() 2665 { 2666 SolarMutexGuard aSolarGuard; 2667 return mnUserPaintColor; 2668 } 2669 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 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 2700 sal_Bool SAL_CALL SlideshowImpl::isRunning( ) 2701 { 2702 SolarMutexGuard aSolarGuard; 2703 return mxShow.is(); 2704 } 2705 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 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 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 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 2846 void SAL_CALL SlideshowImpl::gotoPreviousSlide( ) 2847 { 2848 gotoPreviousSlide(false); 2849 } 2850 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 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 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 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 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 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 2984 ::sal_Int32 SAL_CALL SlideshowImpl::getCount( ) 2985 { 2986 return getSlideCount(); 2987 } 2988 2989 css::uno::Any SAL_CALL SlideshowImpl::getByIndex( ::sal_Int32 Index ) 2990 { 2991 return Any( getSlideByIndex( Index ) ); 2992 } 2993 2994 css::uno::Type SAL_CALL SlideshowImpl::getElementType( ) 2995 { 2996 return cppu::UnoType<XDrawPage>::get(); 2997 } 2998 2999 sal_Bool SAL_CALL SlideshowImpl::hasElements( ) 3000 { 3001 return getSlideCount() != 0; 3002 } 3003 3004 Reference< XSlideShow > SAL_CALL SlideshowImpl::getSlideShow() 3005 { 3006 return mxShow; 3007 } 3008 3009 PresentationSettingsEx::PresentationSettingsEx( const PresentationSettingsEx& r ) 3010 : PresentationSettings( r ) 3011 , mbRehearseTimings(r.mbRehearseTimings) 3012 , mbPreview(r.mbPreview) 3013 , mpParentWindow( nullptr ) 3014 { 3015 } 3016 3017 PresentationSettingsEx::PresentationSettingsEx( PresentationSettings const & r ) 3018 : PresentationSettings( r ) 3019 , mbRehearseTimings(false) 3020 , mbPreview(false) 3021 , mpParentWindow(nullptr) 3022 { 3023 } 3024 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 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 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 3132 SlideShowListenerProxy::~SlideShowListenerProxy() 3133 { 3134 } 3135 3136 void SlideShowListenerProxy::addAsSlideShowListener() 3137 { 3138 if( mxSlideShow.is() ) 3139 { 3140 Reference< XSlideShowListener > xSlideShowListener( this ); 3141 mxSlideShow->addSlideShowListener( xSlideShowListener ); 3142 } 3143 } 3144 3145 void SlideShowListenerProxy::removeAsSlideShowListener() 3146 { 3147 if( mxSlideShow.is() ) 3148 { 3149 Reference< XSlideShowListener > xSlideShowListener( this ); 3150 mxSlideShow->removeSlideShowListener( xSlideShowListener ); 3151 } 3152 } 3153 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 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 3172 void SlideShowListenerProxy::addSlideShowListener( const css::uno::Reference< css::presentation::XSlideShowListener >& xListener ) 3173 { 3174 maListeners.addInterface(xListener); 3175 } 3176 3177 void SlideShowListenerProxy::removeSlideShowListener( const css::uno::Reference< css::presentation::XSlideShowListener >& xListener ) 3178 { 3179 maListeners.removeInterface(xListener); 3180 } 3181 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( 3189 [&] (Reference<XAnimationListener> const& xListener) { 3190 return xListener->beginEvent(xNode); 3191 } ); 3192 } 3193 } 3194 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( 3202 [&] (Reference<XAnimationListener> const& xListener) { 3203 return xListener->endEvent(xNode); 3204 } ); 3205 } 3206 } 3207 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( 3215 [&] (Reference<XAnimationListener> const& xListener) { 3216 return xListener->repeat(xNode, nRepeat); 3217 } ); 3218 } 3219 } 3220 3221 // css::presentation::XSlideShowListener: 3222 3223 void SAL_CALL SlideShowListenerProxy::paused( ) 3224 { 3225 ::osl::MutexGuard aGuard( m_aMutex ); 3226 3227 maListeners.forEach( 3228 [](uno::Reference<presentation::XSlideShowListener> const& xListener) 3229 { 3230 xListener->paused(); 3231 }); 3232 } 3233 3234 void SAL_CALL SlideShowListenerProxy::resumed( ) 3235 { 3236 ::osl::MutexGuard aGuard( m_aMutex ); 3237 3238 maListeners.forEach( 3239 [](uno::Reference<presentation::XSlideShowListener> const& xListener) 3240 { 3241 xListener->resumed(); 3242 }); 3243 } 3244 3245 void SAL_CALL SlideShowListenerProxy::slideTransitionStarted( ) 3246 { 3247 ::osl::MutexGuard aGuard( m_aMutex ); 3248 3249 maListeners.forEach( 3250 [](uno::Reference<presentation::XSlideShowListener> const& xListener) 3251 { 3252 xListener->slideTransitionStarted(); 3253 }); 3254 } 3255 3256 void SAL_CALL SlideShowListenerProxy::slideTransitionEnded( ) 3257 { 3258 ::osl::MutexGuard aGuard( m_aMutex ); 3259 3260 maListeners.forEach( 3261 [](uno::Reference<presentation::XSlideShowListener> const& xListener) 3262 { 3263 xListener->slideTransitionEnded (); 3264 }); 3265 } 3266 3267 void SAL_CALL SlideShowListenerProxy::slideAnimationsEnded( ) 3268 { 3269 ::osl::MutexGuard aGuard( m_aMutex ); 3270 3271 maListeners.forEach( 3272 [](uno::Reference<presentation::XSlideShowListener> const& xListener) 3273 { 3274 xListener->slideAnimationsEnded (); 3275 }); 3276 } 3277 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( 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 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( 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 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 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
