tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / sd / source / ui / slideshow / slideshow.cxx
blob49cb4f489bf5d90d9d2c6b18e8f54e7346c44ae5
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/beans/PropertyAttribute.hpp>
21 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
22 #include <com/sun/star/frame/XDispatchProvider.hpp>
23 #include <com/sun/star/util/URL.hpp>
25 #include <comphelper/propertyvalue.hxx>
26 #include <cppuhelper/supportsservice.hxx>
28 #include <sal/log.hxx>
29 #include <vcl/svapp.hxx>
30 #include <vcl/wrkwin.hxx>
31 #include <svx/svdpool.hxx>
32 #include <svx/svdlayer.hxx>
33 #include <svl/itemprop.hxx>
35 #include <sfx2/bindings.hxx>
36 #include <sfx2/viewfrm.hxx>
37 #include <sfx2/sfxsids.hrc>
39 #include <framework/FrameworkHelper.hxx>
40 #include <comphelper/extract.hxx>
42 #include <FrameView.hxx>
43 #include <createpresentation.hxx>
44 #include <unomodel.hxx>
45 #include <slideshow.hxx>
46 #include "slideshowimpl.hxx"
47 #include <sdattr.hrc>
48 #include <sdmod.hxx>
49 #include <FactoryIds.hxx>
50 #include <DrawDocShell.hxx>
51 #include <ViewShell.hxx>
52 #include <ViewShellBase.hxx>
53 #include "SlideShowRestarter.hxx"
54 #include <DrawController.hxx>
55 #include <PresentationViewShell.hxx>
56 #include <customshowlist.hxx>
57 #include <unopage.hxx>
58 #include <sdpage.hxx>
59 #include <cusshow.hxx>
60 #include <optsitem.hxx>
61 #include <strings.hrc>
62 #include <sdresid.hxx>
64 using ::com::sun::star::presentation::XSlideShowController;
65 using ::sd::framework::FrameworkHelper;
66 using ::com::sun::star::awt::XWindow;
67 using namespace ::sd;
68 using namespace ::cppu;
69 using namespace ::com::sun::star;
70 using namespace ::com::sun::star::uno;
71 using namespace ::com::sun::star::drawing;
72 using namespace ::com::sun::star::beans;
73 using namespace ::com::sun::star::lang;
74 using namespace ::com::sun::star::animations;
76 namespace {
77 /** This local version of the work window overrides DataChanged() so that it
78 can restart the slide show when a display is added or removed.
80 class FullScreenWorkWindow : public WorkWindow
82 public:
83 FullScreenWorkWindow (
84 const ::rtl::Reference<SlideShow>& rpSlideShow,
85 ViewShellBase* pViewShellBase)
86 : WorkWindow(nullptr, WB_HIDE | WB_CLIPCHILDREN),
87 mpRestarter(std::make_shared<SlideShowRestarter>(rpSlideShow, pViewShellBase))
90 void Restart(bool bForce)
92 mpRestarter->Restart(bForce);
95 virtual void DataChanged (const DataChangedEvent& rEvent) override
97 if (rEvent.GetType() == DataChangedEventType::DISPLAY)
98 Restart(false);
101 private:
102 ::std::shared_ptr<SlideShowRestarter> mpRestarter;
106 static std::span<const SfxItemPropertyMapEntry> ImplGetPresentationPropertyMap()
108 // NOTE: First member must be sorted
109 static const SfxItemPropertyMapEntry aPresentationPropertyMap_Impl[] =
111 { u"AllowAnimations"_ustr, ATTR_PRESENT_ANIMATION_ALLOWED, cppu::UnoType<bool>::get(), 0, 0 },
112 { u"CustomShow"_ustr, ATTR_PRESENT_CUSTOMSHOW, ::cppu::UnoType<OUString>::get(), 0, 0 },
113 { u"Display"_ustr, ATTR_PRESENT_DISPLAY, ::cppu::UnoType<sal_Int32>::get(), 0, 0 },
114 { u"FirstPage"_ustr, ATTR_PRESENT_DIANAME, ::cppu::UnoType<OUString>::get(), 0, 0 },
115 { u"IsAlwaysOnTop"_ustr, ATTR_PRESENT_ALWAYS_ON_TOP, cppu::UnoType<bool>::get(), 0, 0 },
116 { u"IsAutomatic"_ustr, ATTR_PRESENT_MANUEL, cppu::UnoType<bool>::get(), 0, 0 },
117 { u"IsEndless"_ustr, ATTR_PRESENT_ENDLESS, cppu::UnoType<bool>::get(), 0, 0 },
118 { u"IsFullScreen"_ustr, ATTR_PRESENT_FULLSCREEN, cppu::UnoType<bool>::get(), 0, 0 },
119 { u"IsShowAll"_ustr, ATTR_PRESENT_ALL, cppu::UnoType<bool>::get(), 0, 0 },
120 { u"IsMouseVisible"_ustr, ATTR_PRESENT_MOUSE, cppu::UnoType<bool>::get(), 0, 0 },
121 { u"IsShowLogo"_ustr, ATTR_PRESENT_SHOW_PAUSELOGO, cppu::UnoType<bool>::get(), 0, 0 },
122 { u"IsTransitionOnClick"_ustr, ATTR_PRESENT_CHANGE_PAGE, cppu::UnoType<bool>::get(), 0, 0 },
123 { u"Pause"_ustr, ATTR_PRESENT_PAUSE_TIMEOUT, ::cppu::UnoType<sal_Int32>::get(), 0, 0 },
124 { u"StartWithNavigator"_ustr, ATTR_PRESENT_NAVIGATOR, cppu::UnoType<bool>::get(), 0, 0 },
125 { u"UsePen"_ustr, ATTR_PRESENT_PEN, cppu::UnoType<bool>::get(), 0, 0 },
128 return aPresentationPropertyMap_Impl;
132 SlideShow::SlideShow( SdDrawDocument* pDoc )
133 : maPropSet(ImplGetPresentationPropertyMap(), SdrObject::GetGlobalDrawObjectItemPool())
134 , mbIsInStartup(false)
135 , mpDoc( pDoc )
136 , mpCurrentViewShellBase( nullptr )
137 , mpFullScreenViewShellBase( nullptr )
138 , mpFullScreenFrameView( nullptr )
139 , mnInPlaceConfigEvent( nullptr )
143 void SlideShow::ThrowIfDisposed() const
145 if( mpDoc == nullptr )
146 throw DisposedException();
149 /// used by the model to create a slideshow for it
150 rtl::Reference< SlideShow > SlideShow::Create( SdDrawDocument* pDoc )
152 return new SlideShow( pDoc );
155 rtl::Reference< SlideShow > SlideShow::GetSlideShow( SdDrawDocument const * pDocument )
157 rtl::Reference< SlideShow > xRet;
159 if( pDocument )
160 xRet = GetSlideShow( *pDocument );
162 return xRet;
165 rtl::Reference< SlideShow > SlideShow::GetSlideShow( SdDrawDocument const & rDocument )
167 return rtl::Reference< SlideShow >(
168 dynamic_cast< SlideShow* >( rDocument.getPresentation().get() ) );
171 rtl::Reference< SlideShow > SlideShow::GetSlideShow( ViewShellBase const & rBase )
173 return GetSlideShow( rBase.GetDocument() );
176 css::uno::Reference< css::presentation::XSlideShowController > SlideShow::GetSlideShowController(ViewShellBase const & rBase )
178 rtl::Reference< SlideShow > xSlideShow( GetSlideShow( rBase ) );
180 Reference< XSlideShowController > xRet;
181 if( xSlideShow.is() )
182 xRet = xSlideShow->getController();
184 return xRet;
187 bool SlideShow::StartPreview( ViewShellBase const & rBase,
188 const css::uno::Reference< css::drawing::XDrawPage >& xDrawPage,
189 const css::uno::Reference< css::animations::XAnimationNode >& xAnimationNode )
191 rtl::Reference< SlideShow > xSlideShow( GetSlideShow( rBase ) );
192 if( !xSlideShow.is() )
193 return false;
195 // end an already running IASS Preview (when someone is fast)
196 if (xSlideShow->IsInteractiveSlideshow() && xSlideShow->isInteractiveSetup())
197 xSlideShow->endInteractivePreview();
199 // check if IASS re-use of running Slideshow can/should be done
200 // and do it
201 if (xSlideShow->IsInteractiveSlideshow() && xSlideShow->isFullScreen()) // IASS
202 return xSlideShow->startInteractivePreview( xDrawPage, xAnimationNode );
204 // fallback to usual mode
205 xSlideShow->startPreview( xDrawPage, xAnimationNode );
206 return true;
209 void SlideShow::Stop( ViewShellBase const & rBase )
211 rtl::Reference< SlideShow > xSlideShow( GetSlideShow( rBase ) );
212 if( xSlideShow.is() )
213 xSlideShow->end();
216 bool SlideShow::IsRunning( ViewShellBase const & rBase )
218 rtl::Reference< SlideShow > xSlideShow( GetSlideShow( rBase ) );
219 return xSlideShow.is() && xSlideShow->isRunning();
222 bool SlideShow::IsRunning( const ViewShell& rViewShell )
224 rtl::Reference< SlideShow > xSlideShow( GetSlideShow( rViewShell.GetViewShellBase() ) );
225 return xSlideShow.is() && xSlideShow->isRunning() && (xSlideShow->mxController->getViewShell() == &rViewShell);
228 /// returns true if the interactive slideshow mode is activated
229 bool SlideShow::IsInteractiveSlideshow(const ViewShellBase* pViewShellBase)
231 if (nullptr == pViewShellBase)
232 return false;
233 rtl::Reference< SlideShow > xSlideShow(GetSlideShow(*pViewShellBase));
234 if (!xSlideShow.is())
235 return false;
236 return xSlideShow->IsInteractiveSlideshow();
239 bool SlideShow::IsInteractiveSlideshow() const
241 return mpDoc->getPresentationSettings().mbInteractive;
244 void SlideShow::CreateController( ViewShell* pViewSh, ::sd::View* pView, vcl::Window* pParentWindow )
246 SAL_INFO_IF( !mxController.is(), "sd.slideshow", "sd::SlideShow::CreateController(), clean up old controller first!" );
248 Reference< XPresentation2 > xThis( this );
250 // Reset mbIsInStartup. From here mxController.is() is used to prevent
251 // multiple slide show instances for one document.
252 mxController.set(new SlideshowImpl(xThis, pViewSh, pView, mpDoc, pParentWindow));
254 mbIsInStartup = false;
258 // XServiceInfo
259 OUString SAL_CALL SlideShow::getImplementationName( )
261 return u"com.sun.star.comp.sd.SlideShow"_ustr;
264 sal_Bool SAL_CALL SlideShow::supportsService( const OUString& ServiceName )
266 return cppu::supportsService( this, ServiceName );
269 Sequence< OUString > SAL_CALL SlideShow::getSupportedServiceNames( )
271 return { u"com.sun.star.presentation.Presentation"_ustr };
274 // XPropertySet
275 Reference< XPropertySetInfo > SAL_CALL SlideShow::getPropertySetInfo()
277 SolarMutexGuard aGuard;
278 static Reference< XPropertySetInfo > xInfo = maPropSet.getPropertySetInfo();
279 return xInfo;
282 void SAL_CALL SlideShow::setPropertyValue( const OUString& aPropertyName, const Any& aValue )
284 SolarMutexGuard aGuard;
285 ThrowIfDisposed();
287 sd::PresentationSettings& rPresSettings = mpDoc->getPresentationSettings();
289 const SfxItemPropertyMapEntry* pEntry = maPropSet.getPropertyMapEntry(aPropertyName);
291 if( pEntry && ((pEntry->nFlags & PropertyAttribute::READONLY) != 0) )
292 throw PropertyVetoException();
294 bool bValuesChanged = false;
295 bool bIllegalArgument = true;
297 switch( pEntry ? pEntry->nWID : -1 )
299 case ATTR_PRESENT_ALL:
301 bool bVal = false;
303 if( aValue >>= bVal )
305 bIllegalArgument = false;
307 if( rPresSettings.mbAll != bVal )
309 rPresSettings.mbAll = bVal;
310 bValuesChanged = true;
311 if( bVal )
312 rPresSettings.mbCustomShow = false;
315 break;
317 case ATTR_PRESENT_CHANGE_PAGE:
319 bool bVal = false;
321 if( aValue >>= bVal )
323 bIllegalArgument = false;
325 if( bVal == rPresSettings.mbLockedPages )
327 bValuesChanged = true;
328 rPresSettings.mbLockedPages = !bVal;
331 break;
334 case ATTR_PRESENT_ANIMATION_ALLOWED:
336 bool bVal = false;
338 if( aValue >>= bVal )
340 bIllegalArgument = false;
342 if(rPresSettings.mbAnimationAllowed != bVal)
344 bValuesChanged = true;
345 rPresSettings.mbAnimationAllowed = bVal;
348 break;
350 case ATTR_PRESENT_CUSTOMSHOW:
352 OUString aShowName;
353 if( aValue >>= aShowName )
355 bIllegalArgument = false;
357 SdCustomShowList* pCustomShowList = mpDoc->GetCustomShowList();
358 if(pCustomShowList)
360 SdCustomShow* pCustomShow;
361 for( pCustomShow = pCustomShowList->First(); pCustomShow != nullptr; pCustomShow = pCustomShowList->Next() )
363 if( pCustomShow->GetName() == aShowName )
364 break;
367 rPresSettings.mbCustomShow = true;
368 bValuesChanged = true;
371 break;
373 case ATTR_PRESENT_ENDLESS:
375 bool bVal = false;
377 if( aValue >>= bVal )
379 bIllegalArgument = false;
381 if( rPresSettings.mbEndless != bVal)
383 bValuesChanged = true;
384 rPresSettings.mbEndless = bVal;
387 break;
389 case ATTR_PRESENT_FULLSCREEN:
391 bool bVal = false;
393 if( aValue >>= bVal )
395 bIllegalArgument = false;
396 if( rPresSettings.mbFullScreen != bVal)
398 bValuesChanged = true;
399 rPresSettings.mbFullScreen = bVal;
402 break;
404 case ATTR_PRESENT_DIANAME:
406 OUString aPresPage;
407 aValue >>= aPresPage;
408 bIllegalArgument = false;
409 if( (rPresSettings.maPresPage != aPresPage) || !rPresSettings.mbCustomShow || !rPresSettings.mbAll )
411 bValuesChanged = true;
412 rPresSettings.maPresPage = getUiNameFromPageApiNameImpl(aPresPage);
413 rPresSettings.mbCustomShow = false;
414 rPresSettings.mbAll = false;
416 break;
418 case ATTR_PRESENT_MANUEL:
420 bool bVal = false;
422 if( aValue >>= bVal )
424 bIllegalArgument = false;
426 if( rPresSettings.mbManual != bVal)
428 bValuesChanged = true;
429 rPresSettings.mbManual = bVal;
432 break;
434 case ATTR_PRESENT_MOUSE:
436 bool bVal = false;
438 if( aValue >>= bVal )
440 bIllegalArgument = false;
441 if( rPresSettings.mbMouseVisible != bVal)
443 bValuesChanged = true;
444 rPresSettings.mbMouseVisible = bVal;
447 break;
449 case ATTR_PRESENT_ALWAYS_ON_TOP:
451 bool bVal = false;
453 if( aValue >>= bVal )
455 bIllegalArgument = false;
457 if( rPresSettings.mbAlwaysOnTop != bVal)
459 bValuesChanged = true;
460 rPresSettings.mbAlwaysOnTop = bVal;
463 break;
465 case ATTR_PRESENT_NAVIGATOR:
466 bIllegalArgument = false;
467 //ignored, but exists in some older documents
468 break;
469 case ATTR_PRESENT_PEN:
471 bool bVal = false;
473 if( aValue >>= bVal )
475 bIllegalArgument = false;
477 if(rPresSettings.mbMouseAsPen != bVal)
479 bValuesChanged = true;
480 rPresSettings.mbMouseAsPen = bVal;
483 break;
485 case ATTR_PRESENT_PAUSE_TIMEOUT:
487 sal_Int32 nValue = 0;
488 if( (aValue >>= nValue) && (nValue >= 0) )
490 bIllegalArgument = false;
491 if( rPresSettings.mnPauseTimeout != nValue )
493 bValuesChanged = true;
494 rPresSettings.mnPauseTimeout = nValue;
497 break;
499 case ATTR_PRESENT_SHOW_PAUSELOGO:
501 bool bVal = false;
503 if( aValue >>= bVal )
505 bIllegalArgument = false;
507 if( rPresSettings.mbShowPauseLogo != bVal )
509 bValuesChanged = true;
510 rPresSettings.mbShowPauseLogo = bVal;
513 break;
515 case ATTR_PRESENT_DISPLAY:
517 sal_Int32 nDisplay = 0;
518 if( aValue >>= nDisplay )
520 bIllegalArgument = false;
522 SdOptions* pOptions = SdModule::get()->GetSdOptions(DocumentType::Impress);
523 pOptions->SetDisplay( nDisplay );
525 FullScreenWorkWindow *pWin = dynamic_cast<FullScreenWorkWindow *>(GetWorkWindow());
526 if( !pWin )
527 return;
528 pWin->Restart(true);
530 break;
533 default:
534 throw UnknownPropertyException( OUString::number(pEntry ? pEntry->nWID : -1), static_cast<cppu::OWeakObject*>(this));
537 if( bIllegalArgument )
538 throw IllegalArgumentException();
540 if( bValuesChanged )
541 mpDoc->SetChanged();
544 Any SAL_CALL SlideShow::getPropertyValue( const OUString& PropertyName )
546 SolarMutexGuard aGuard;
547 ThrowIfDisposed();
549 const sd::PresentationSettings& rPresSettings = mpDoc->getPresentationSettings();
551 const SfxItemPropertyMapEntry* pEntry = maPropSet.getPropertyMapEntry(PropertyName);
553 switch( pEntry ? pEntry->nWID : -1 )
555 case ATTR_PRESENT_ALL:
556 return Any( !rPresSettings.mbCustomShow && rPresSettings.mbAll );
557 case ATTR_PRESENT_CHANGE_PAGE:
558 return Any( !rPresSettings.mbLockedPages );
559 case ATTR_PRESENT_ANIMATION_ALLOWED:
560 return Any( rPresSettings.mbAnimationAllowed );
561 case ATTR_PRESENT_CUSTOMSHOW:
563 SdCustomShowList* pList = mpDoc->GetCustomShowList();
564 SdCustomShow* pShow = (pList && rPresSettings.mbCustomShow) ? pList->GetCurObject() : nullptr;
565 OUString aShowName;
567 if(pShow)
568 aShowName = pShow->GetName();
570 return Any( aShowName );
572 case ATTR_PRESENT_ENDLESS:
573 return Any( rPresSettings.mbEndless );
574 case ATTR_PRESENT_FULLSCREEN:
575 return Any( rPresSettings.mbFullScreen );
576 case ATTR_PRESENT_DIANAME:
578 OUString aSlideName;
580 if( !rPresSettings.mbCustomShow && !rPresSettings.mbAll )
581 aSlideName = getPageApiNameFromUiName( rPresSettings.maPresPage );
583 return Any( aSlideName );
585 case ATTR_PRESENT_MANUEL:
586 return Any( rPresSettings.mbManual );
587 case ATTR_PRESENT_MOUSE:
588 return Any( rPresSettings.mbMouseVisible );
589 case ATTR_PRESENT_ALWAYS_ON_TOP:
590 return Any( rPresSettings.mbAlwaysOnTop );
591 case ATTR_PRESENT_NAVIGATOR:
592 return Any( false );
593 case ATTR_PRESENT_PEN:
594 return Any( rPresSettings.mbMouseAsPen );
595 case ATTR_PRESENT_PAUSE_TIMEOUT:
596 return Any( rPresSettings.mnPauseTimeout );
597 case ATTR_PRESENT_SHOW_PAUSELOGO:
598 return Any( rPresSettings.mbShowPauseLogo );
599 case ATTR_PRESENT_DISPLAY:
601 SdOptions* pOptions = SdModule::get()->GetSdOptions(DocumentType::Impress);
602 return Any(pOptions->GetDisplay());
605 default:
606 throw UnknownPropertyException( OUString::number(pEntry ? pEntry->nWID : -1), static_cast<cppu::OWeakObject*>(this));
610 void SAL_CALL SlideShow::addPropertyChangeListener( const OUString& , const Reference< XPropertyChangeListener >& )
614 void SAL_CALL SlideShow::removePropertyChangeListener( const OUString& , const Reference< XPropertyChangeListener >& )
618 void SAL_CALL SlideShow::addVetoableChangeListener( const OUString& , const Reference< XVetoableChangeListener >& )
622 void SAL_CALL SlideShow::removeVetoableChangeListener( const OUString& , const Reference< XVetoableChangeListener >& )
626 // XPresentation
628 void SAL_CALL SlideShow::start()
630 const Sequence< PropertyValue > aArguments;
631 startWithArguments( aArguments );
634 WorkWindow *SlideShow::GetWorkWindow()
636 if( !mpFullScreenViewShellBase )
637 return nullptr;
639 PresentationViewShell* pShell = dynamic_cast<PresentationViewShell*>(mpFullScreenViewShellBase->GetMainViewShell().get());
641 if( !pShell)
642 return nullptr;
644 SfxViewFrame* pFrame = pShell->GetViewFrame();
645 if (!pFrame)
646 return nullptr;
648 return dynamic_cast<WorkWindow*>(pFrame->GetFrame().GetWindow().GetParent());
651 bool SlideShow::IsExitAfterPresenting() const
653 SolarMutexGuard aGuard;
654 ThrowIfDisposed();
655 return mpDoc->IsExitAfterPresenting();
658 void SlideShow::SetExitAfterPresenting(bool bExit)
660 SolarMutexGuard aGuard;
661 ThrowIfDisposed();
662 mpDoc->SetExitAfterPresenting(bExit);
665 void SAL_CALL SlideShow::end()
667 SolarMutexGuard aGuard;
669 if (IsInteractiveSlideshow() && isInteractiveSetup())
671 // If IASS was active clean that up, but do not end SlideShow
672 endInteractivePreview();
673 return;
676 // The mbIsInStartup flag should have been reset during the start of the
677 // slide show. Reset it here just in case that something has horribly
678 // gone wrong.
679 assert(!mbIsInStartup);
681 rtl::Reference< SlideshowImpl > xController( mxController );
682 if( !xController.is() )
683 return;
685 mxController.clear();
687 if( mpFullScreenFrameView )
689 delete mpFullScreenFrameView;
690 mpFullScreenFrameView = nullptr;
693 ViewShellBase* pFullScreenViewShellBase = mpFullScreenViewShellBase;
694 mpFullScreenViewShellBase = nullptr;
696 // dispose before fullscreen window changes screens
697 // (potentially). If this needs to be moved behind
698 // pWorkWindow->StartPresentationMode() again, read issue
699 // pWorkWindow->i94007 & implement the solution outlined
700 // there.
701 xController->dispose();
703 if( pFullScreenViewShellBase )
705 PresentationViewShell* pShell = dynamic_cast<PresentationViewShell*>(pFullScreenViewShellBase->GetMainViewShell().get());
707 if( pShell && pShell->GetViewFrame() )
709 WorkWindow* pWorkWindow = dynamic_cast<WorkWindow*>(pShell->GetViewFrame()->GetFrame().GetWindow().GetParent());
710 if( pWorkWindow )
712 pWorkWindow->StartPresentationMode( (mxController.is() && mxController->maPresSettings.mbAlwaysOnTop)
713 ? PresentationFlags::HideAllApps : PresentationFlags::NONE );
718 if( pFullScreenViewShellBase )
720 PresentationViewShell* pShell = nullptr;
722 // Get the shell pointer in its own scope to be sure that
723 // the shared_ptr to the shell is released before DoClose()
724 // is called.
725 ::std::shared_ptr<ViewShell> pSharedView (pFullScreenViewShellBase->GetMainViewShell());
726 pShell = dynamic_cast<PresentationViewShell*>(pSharedView.get());
728 if( pShell && pShell->GetViewFrame() )
729 pShell->GetViewFrame()->DoClose();
731 else if( mpCurrentViewShellBase )
733 ViewShell* pViewShell = mpCurrentViewShellBase->GetMainViewShell().get();
735 if( pViewShell )
737 FrameView* pFrameView = pViewShell->GetFrameView();
739 if( pFrameView && (pFrameView->GetPresentationViewShellId() != SID_VIEWSHELL0) )
741 ViewShell::ShellType ePreviousType (pFrameView->GetPreviousViewShellType());
742 pFrameView->SetPreviousViewShellType(ViewShell::ST_NONE);
744 pFrameView->SetPresentationViewShellId(SID_VIEWSHELL0);
745 pFrameView->SetPreviousViewShellType(pViewShell->GetShellType());
747 framework::FrameworkHelper::Instance(*mpCurrentViewShellBase)->RequestView(
748 framework::FrameworkHelper::GetViewURL(ePreviousType),
749 framework::FrameworkHelper::msCenterPaneURL);
751 pViewShell->GetViewFrame()->GetBindings().InvalidateAll( true );
756 if( mpCurrentViewShellBase )
758 if (ViewShell* const pViewShell = mpCurrentViewShellBase->GetMainViewShell().get())
760 // invalidate the view shell so the presentation slot will be re-enabled
761 // and the rehearsing will be updated
762 pViewShell->Invalidate();
764 if( xController->meAnimationMode ==ANIMATIONMODE_SHOW )
766 // switch to the previously visible Slide
767 DrawViewShell* pDrawViewShell = dynamic_cast<DrawViewShell*>( pViewShell );
768 if( pDrawViewShell )
769 pDrawViewShell->SwitchPage( static_cast<sal_uInt16>(xController->getRestoreSlide()) );
770 else
772 DrawController& rDrawController =
773 *mpCurrentViewShellBase->GetDrawController();
774 rDrawController.setCurrentPage(
775 Reference<XDrawPage>(
776 mpDoc->GetSdPage(xController->getRestoreSlide(), PageKind::Standard)->getUnoPage(),
777 UNO_QUERY));
781 if( pViewShell->GetDoc()->IsExitAfterPresenting() )
783 pViewShell->GetDoc()->SetExitAfterPresenting( false );
785 Reference<frame::XDispatchProvider> xProvider(pViewShell->GetViewShellBase().GetController()->getFrame(),
786 UNO_QUERY);
787 if( xProvider.is() )
789 util::URL aURL;
790 aURL.Complete = ".uno:CloseFrame";
792 uno::Reference< frame::XDispatch > xDispatch(
793 xProvider->queryDispatch(
794 aURL, OUString(), 0));
795 if( xDispatch.is() )
797 xDispatch->dispatch(aURL,
798 uno::Sequence< beans::PropertyValue >());
803 // In case mbMouseAsPen was set, a new layer DrawnInSlideshow might have been generated
804 // during slideshow, which is not known to FrameView yet.
805 if (any2bool(getPropertyValue(u"UsePen"_ustr))
806 && pViewShell->GetDoc()->GetLayerAdmin().GetLayer(u"DrawnInSlideshow"_ustr))
808 SdrLayerIDSet aDocLayerIDSet;
809 pViewShell->GetDoc()->GetLayerAdmin().getVisibleLayersODF(aDocLayerIDSet);
810 if (pViewShell->GetFrameView()->GetVisibleLayers() != aDocLayerIDSet)
812 pViewShell->GetFrameView()->SetVisibleLayers(aDocLayerIDSet);
814 pViewShell->GetDoc()->GetLayerAdmin().getPrintableLayersODF(aDocLayerIDSet);
815 if (pViewShell->GetFrameView()->GetPrintableLayers() != aDocLayerIDSet)
817 pViewShell->GetFrameView()->SetPrintableLayers(aDocLayerIDSet);
819 pViewShell->GetDoc()->GetLayerAdmin().getLockedLayersODF(aDocLayerIDSet);
820 if (pViewShell->GetFrameView()->GetLockedLayers() != aDocLayerIDSet)
822 pViewShell->GetFrameView()->SetLockedLayers(aDocLayerIDSet);
824 pViewShell->InvalidateWindows();
827 // Fire the acc focus event when focus is switched back. The above method
828 // mpCurrentViewShellBase->GetWindow()->GrabFocus() will set focus to WorkWindow
829 // instead of the sd::window, so here call Shell's method to fire the focus event
830 pViewShell->SwitchActiveViewFireFocus();
833 mpCurrentViewShellBase = nullptr;
836 void SAL_CALL SlideShow::rehearseTimings()
838 Sequence< PropertyValue > aArguments{ comphelper::makePropertyValue(u"RehearseTimings"_ustr, true) };
839 startWithArguments( aArguments );
842 // XPresentation2
844 void SAL_CALL SlideShow::startWithArguments(const Sequence< PropertyValue >& rArguments)
846 SolarMutexGuard aGuard;
847 ThrowIfDisposed();
849 // Stop a running show before starting a new one.
850 if( mxController.is() )
852 assert(!mbIsInStartup);
853 end();
855 else if (mbIsInStartup)
857 // We are already somewhere in process of starting a slide show but
858 // have not yet got to the point where mxController is set. There
859 // is not yet a slide show to end so return silently.
860 return;
863 // Prevent multiple instance of the SlideShow class for one document.
864 mbIsInStartup = true;
866 mxCurrentSettings = std::make_shared<PresentationSettingsEx>( mpDoc->getPresentationSettings() );
867 mxCurrentSettings->SetArguments( rArguments );
869 // if there is no view shell base set, use the current one or the first using this document
870 if( mpCurrentViewShellBase == nullptr )
872 // first check current
873 ::sd::ViewShellBase* pBase = ::sd::ViewShellBase::GetViewShellBase( SfxViewFrame::Current() );
874 if( pBase && pBase->GetDocument() == mpDoc )
876 mpCurrentViewShellBase = pBase;
878 else
880 // current is not ours, so get first from ours
881 mpCurrentViewShellBase = ::sd::ViewShellBase::GetViewShellBase( SfxViewFrame::GetFirst( mpDoc->GetDocSh() ) );
885 // #i118456# make sure TextEdit changes get pushed to model.
886 // mpDrawView is tested against NULL above already.
887 if(mpCurrentViewShellBase)
889 ViewShell* pViewShell = mpCurrentViewShellBase->GetMainViewShell().get();
891 if(pViewShell && pViewShell->GetView())
893 pViewShell->GetView()->SdrEndTextEdit();
897 // Start either a full-screen or an in-place show.
898 if(mxCurrentSettings->mbFullScreen && !mxCurrentSettings->mbPreview)
899 StartFullscreenPresentation();
900 else
901 StartInPlacePresentation();
905 sal_Bool SAL_CALL SlideShow::isRunning( )
907 SolarMutexGuard aGuard;
908 return mxController.is() && mxController->isRunning();
911 Reference< XSlideShowController > SAL_CALL SlideShow::getController( )
913 ThrowIfDisposed();
915 return mxController;
918 // XComponent
920 void SlideShow::disposing(std::unique_lock<std::mutex>&)
922 SolarMutexGuard aGuard;
924 if( mnInPlaceConfigEvent )
926 Application::RemoveUserEvent( mnInPlaceConfigEvent );
927 mnInPlaceConfigEvent = nullptr;
930 if( mxController.is() )
932 mxController->dispose();
933 mxController.clear();
936 mpCurrentViewShellBase = nullptr;
937 mpFullScreenViewShellBase = nullptr;
938 mpDoc = nullptr;
941 bool SlideShow::startInteractivePreview( const Reference< XDrawPage >& xDrawPage, const Reference< XAnimationNode >& xAnimationNode )
943 if (!mxController.is())
944 return false;
946 mxController->startInteractivePreview(xDrawPage, xAnimationNode);
947 return mxController->isInteractiveSetup();
950 bool SlideShow::isInteractiveSetup() const
952 if (!mxController.is())
953 return false;
955 return mxController->isInteractiveSetup();
958 void SlideShow::endInteractivePreview()
960 mxController->endInteractivePreview();
963 void SlideShow::startPreview( const Reference< XDrawPage >& xDrawPage, const Reference< XAnimationNode >& xAnimationNode )
965 Sequence< PropertyValue > aArguments{
966 comphelper::makePropertyValue(u"Preview"_ustr, true),
967 comphelper::makePropertyValue(u"FirstPage"_ustr, xDrawPage),
968 comphelper::makePropertyValue(u"AnimationNode"_ustr, xAnimationNode),
969 comphelper::makePropertyValue(u"ParentWindow"_ustr, Reference< XWindow >()),
972 startWithArguments( aArguments );
975 OutputDevice* SlideShow::getShowWindow()
977 return mxController.is() ? mxController->mpShowWindow->GetOutDev() : nullptr;
980 int SlideShow::getAnimationMode() const
982 return mxController.is() ? mxController->meAnimationMode : ANIMATIONMODE_SHOW;
985 void SlideShow::jumpToPageIndex( sal_Int32 nPageIndex )
987 if( mxController.is() )
988 mxController->displaySlideIndex( nPageIndex );
991 void SlideShow::jumpToPageNumber( sal_Int32 nPageNumber )
993 if( mxController.is() )
994 mxController->displaySlideNumber( nPageNumber );
997 sal_Int32 SlideShow::getCurrentPageNumber() const
999 return mxController.is() ? mxController->getCurrentSlideNumber() : 0;
1002 void SlideShow::jumpToBookmark( const OUString& sBookmark )
1004 if( mxController.is() )
1005 mxController->jumpToBookmark( sBookmark );
1008 bool SlideShow::isFullScreen() const
1010 return mxController.is() && mxController->maPresSettings.mbFullScreen;
1013 void SlideShow::resize( const Size &rSize )
1015 if( mxController.is() )
1016 mxController->resize( rSize );
1019 bool SlideShow::activate( ViewShellBase& rBase )
1021 if( (mpFullScreenViewShellBase == &rBase) && !mxController.is() )
1023 ::std::shared_ptr<PresentationViewShell> pShell = std::dynamic_pointer_cast<PresentationViewShell>(rBase.GetMainViewShell());
1024 if (pShell != nullptr)
1026 pShell->FinishInitialization( mpFullScreenFrameView );
1027 mpFullScreenFrameView = nullptr;
1029 CreateController( pShell.get(), pShell->GetView(), rBase.GetViewWindow() );
1031 if (!mxController->startShow(mxCurrentSettings.get()))
1032 return false;
1034 pShell->Resize();
1035 // Defer the sd::ShowWindow's GrabFocus to here. so that the accessible event can be fired correctly.
1036 pShell->GetActiveWindow()->GrabFocus();
1040 if( mxController.is() )
1041 mxController->activate();
1043 return true;
1046 void SlideShow::deactivate()
1048 mxController->deactivate();
1051 bool SlideShow::keyInput(const KeyEvent& rKEvt)
1053 return mxController.is() && mxController->keyInput(rKEvt);
1056 void SlideShow::paint()
1058 if( mxController.is() )
1059 mxController->paint();
1062 void SlideShow::pause( bool bPause )
1064 if( mxController.is() )
1066 if( bPause )
1067 mxController->pause();
1068 else
1069 mxController->resume();
1073 bool SlideShow::swipe(const CommandGestureSwipeData& rSwipeData)
1075 return mxController.is() && mxController->swipe(rSwipeData);
1078 bool SlideShow::longpress(const CommandGestureLongPressData& rLongPressData)
1080 return mxController.is() && mxController->longpress(rLongPressData);
1083 void SlideShow::StartInPlacePresentationConfigurationCallback()
1085 if( mnInPlaceConfigEvent != nullptr )
1086 Application::RemoveUserEvent( mnInPlaceConfigEvent );
1088 mnInPlaceConfigEvent = Application::PostUserEvent( LINK( this, SlideShow, StartInPlacePresentationConfigurationHdl ) );
1091 IMPL_LINK_NOARG(SlideShow, StartInPlacePresentationConfigurationHdl, void*, void)
1093 mnInPlaceConfigEvent = nullptr;
1094 StartInPlacePresentation();
1097 void SlideShow::StartInPlacePresentation()
1099 if( mpCurrentViewShellBase )
1101 // Save the current view shell type so that it can be restored after the
1102 // show has ended. If there already is a saved shell type then that is
1103 // not overwritten.
1105 ViewShell::ShellType eShell = ViewShell::ST_NONE;
1107 ::std::shared_ptr<FrameworkHelper> pHelper(FrameworkHelper::Instance(*mpCurrentViewShellBase));
1108 ::std::shared_ptr<ViewShell> pMainViewShell(pHelper->GetViewShell(FrameworkHelper::msCenterPaneURL));
1110 if( pMainViewShell )
1111 eShell = pMainViewShell->GetShellType();
1113 if( eShell != ViewShell::ST_IMPRESS )
1115 // Switch temporary to a DrawViewShell which supports the in-place presentation.
1117 if( pMainViewShell )
1119 FrameView* pFrameView = pMainViewShell->GetFrameView();
1120 pFrameView->SetPresentationViewShellId(SID_VIEWSHELL1);
1121 pFrameView->SetPreviousViewShellType (pMainViewShell->GetShellType());
1122 pFrameView->SetPageKind (PageKind::Standard);
1125 pHelper->RequestView( FrameworkHelper::msImpressViewURL, FrameworkHelper::msCenterPaneURL );
1126 pHelper->RunOnConfigurationEvent(
1127 FrameworkHelper::msConfigurationUpdateEndEvent,
1128 [this] (bool const) { return this->StartInPlacePresentationConfigurationCallback(); } );
1129 return;
1131 else
1133 vcl::Window* pParentWindow = mxCurrentSettings->mpParentWindow;
1134 if( pParentWindow == nullptr )
1135 pParentWindow = mpCurrentViewShellBase->GetViewWindow();
1137 CreateController( pMainViewShell.get(), pMainViewShell->GetView(), pParentWindow );
1140 else if( mxCurrentSettings->mpParentWindow )
1142 // no current view shell, but parent window
1143 CreateController( nullptr, nullptr, mxCurrentSettings->mpParentWindow );
1146 if( !mxController.is() )
1147 return;
1149 bool bSuccess = false;
1150 if( mxCurrentSettings && mxCurrentSettings->mbPreview )
1152 bSuccess = mxController->startPreview(mxCurrentSettings->mxStartPage, mxCurrentSettings->mxAnimationNode, mxCurrentSettings->mpParentWindow );
1154 else
1156 bSuccess = mxController->startShow(mxCurrentSettings.get());
1159 if( !bSuccess )
1160 end();
1161 else
1163 if( mpCurrentViewShellBase && ( !mxCurrentSettings || ( mxCurrentSettings && !mxCurrentSettings->mbPreview ) ) )
1164 mpCurrentViewShellBase->GetWindow()->GrabFocus();
1168 void SlideShow::StartFullscreenPresentation( )
1170 // Create the top level window in which the PresentationViewShell(Base)
1171 // will be created. This is done here explicitly so that we can make it
1172 // fullscreen.
1173 const sal_Int32 nDisplay (GetDisplay());
1174 VclPtr<WorkWindow> pWorkWindow = VclPtr<FullScreenWorkWindow>::Create(this, mpCurrentViewShellBase);
1175 pWorkWindow->SetBackground(Wallpaper(COL_BLACK));
1176 OUString Title(SdResId(STR_FULLSCREEN_SLIDESHOW));
1177 Title = Title.replaceFirst("%s",
1178 mpCurrentViewShellBase->GetDocShell()->GetTitle(SFX_TITLE_DETECT));
1179 pWorkWindow->SetText(Title);
1180 pWorkWindow->StartPresentationMode( true, mpDoc->getPresentationSettings().mbAlwaysOnTop ? PresentationFlags::HideAllApps : PresentationFlags::NONE, nDisplay);
1181 // pWorkWindow->ShowFullScreenMode(sal_False, nDisplay);
1183 if (!pWorkWindow->IsVisible())
1184 return;
1186 // Initialize the new presentation view shell with a copy of the
1187 // frame view of the current view shell. This avoids that
1188 // changes made by the presentation have an effect on the other
1189 // view shells.
1190 FrameView* pOriginalFrameView = nullptr;
1191 ::std::shared_ptr<ViewShell> xShell(mpCurrentViewShellBase->GetMainViewShell());
1192 if (xShell)
1193 pOriginalFrameView = xShell->GetFrameView();
1195 delete mpFullScreenFrameView;
1196 mpFullScreenFrameView = new FrameView(mpDoc, pOriginalFrameView);
1198 // The new frame is created hidden. To make it visible and activate the
1199 // new view shell--a prerequisite to process slot calls and initialize
1200 // its panes--a GrabFocus() has to be called later on.
1201 SfxFrame* pNewFrame = SfxFrame::CreateHidden( *mpDoc->GetDocSh(), *pWorkWindow, PRESENTATION_FACTORY_ID );
1202 pNewFrame->SetPresentationMode(true);
1204 mpFullScreenViewShellBase = static_cast<ViewShellBase*>(pNewFrame->GetCurrentViewFrame()->GetViewShell());
1205 if(mpFullScreenViewShellBase != nullptr)
1207 // The following GrabFocus() is responsible for activating the
1208 // new view shell. Without it the screen remains blank (under
1209 // Windows and some Linux variants.)
1210 mpFullScreenViewShellBase->GetWindow()->GrabFocus();
1214 /// convert configuration setting display concept to real screens
1215 sal_Int32 SlideShow::GetDisplay()
1217 sal_Int32 nDisplay = 0;
1219 SdOptions* pOptions = SdModule::get()->GetSdOptions(DocumentType::Impress);
1220 if( pOptions )
1221 nDisplay = pOptions->GetDisplay();
1223 if( nDisplay < 0 )
1224 nDisplay = -1;
1225 else if( nDisplay == 0)
1226 nDisplay = static_cast<sal_Int32>(Application::GetDisplayExternalScreen());
1227 else
1228 nDisplay--;
1230 SAL_INFO("sd", "Presenting on real screen " << nDisplay);
1232 return nDisplay;
1235 bool SlideShow::dependsOn( ViewShellBase const * pViewShellBase )
1237 return mxController.is() && (pViewShellBase == mpCurrentViewShellBase) && mpFullScreenViewShellBase;
1240 Reference< presentation::XPresentation2 > CreatePresentation( const SdDrawDocument& rDocument )
1242 return Reference< presentation::XPresentation2 >( SlideShow::Create( const_cast< SdDrawDocument* >( &rDocument ) ) );
1245 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */