sd/source/ui/slideshow/slideshowimpl.cxx | 106 +++++++++++++++++++++++++++++++ sd/source/ui/slideshow/slideshowimpl.hxx | 5 + 2 files changed, 110 insertions(+), 1 deletion(-)
New commits: commit 7da04200f9f7ac6ed3e573107282da8428ef65e6 Author: Armin Le Grand (allotropia) <armin.le.grand.ext...@allotropia.de> AuthorDate: Wed Nov 15 15:23:20 2023 +0100 Commit: Armin Le Grand <armin.le.gr...@me.com> CommitDate: Mon Nov 20 11:28:54 2023 +0100 Update SlideShow on DrawModel changes It may happen that DrawModel changes while a SlideShow is running, e.g. from EditView/Scripts/UNO API. We can try to suppress these as we already try with EditView in that mode. As an alternative it is also possible to react to these changes in the SLideShow in a useful manner. This is the 2nd try, main change is to do all of this directly in SlideShow, so no chechs/tests in common code are needed. Change-Id: Iaa393d78af1fc40003c83d896508abe31cd790d5 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159447 Tested-by: Jenkins Reviewed-by: Armin Le Grand <armin.le.gr...@me.com> diff --git a/sd/source/ui/slideshow/slideshowimpl.cxx b/sd/source/ui/slideshow/slideshowimpl.cxx index f4f4bfe77019..de62af1ac9e5 100644 --- a/sd/source/ui/slideshow/slideshowimpl.cxx +++ b/sd/source/ui/slideshow/slideshowimpl.cxx @@ -61,6 +61,7 @@ #include <svx/srchdlg.hxx> #include <svx/hyperdlg.hxx> #include <svx/svxids.hrc> +#include <svx/unoapi.hxx> #include <AnimationChildWindow.hxx> #include <notifydocumentevent.hxx> #include "slideshowimpl.hxx" @@ -545,10 +546,19 @@ SlideshowImpl::SlideshowImpl( const Reference< XPresentation2 >& xPresentation, mnUserPaintColor = pOptions->GetPresentationPenColor(); mdUserPaintStrokeWidth = pOptions->GetPresentationPenWidth(); } + + // to be able to react on various changes in the DrawModel, this class + // is now derived from SfxListener and registers itself at the DrawModel + if (nullptr != mpDoc) + StartListening(*mpDoc); } SlideshowImpl::~SlideshowImpl() { + // stop listening to DrawModel (see above) + if (nullptr != mpDoc) + EndListening(*mpDoc); + SdModule *pModule = SD_MOD(); //rhbz#806663 SlideshowImpl can outlive SdModule SdOptions* pOptions = pModule ? @@ -3045,6 +3055,102 @@ sal_Bool SAL_CALL SlideshowImpl::hasElements( ) return getSlideCount() != 0; } +namespace +{ + class AsyncUpdateSlideshow_Impl + { + public: + struct AsyncUpdateSlideshowData + { + SlideshowImpl* pSlideshowImpl; + uno::Reference< css::drawing::XDrawPage > XCurrentSlide; + }; + + static void AsyncUpdateSlideshow( + SlideshowImpl* pSlideshowImpl, + uno::Reference< css::drawing::XDrawPage >& rXCurrentSlide) + { + AsyncUpdateSlideshowData* pNew(new AsyncUpdateSlideshowData); + pNew->pSlideshowImpl = pSlideshowImpl; + pNew->XCurrentSlide = rXCurrentSlide; + Application::PostUserEvent(LINK(nullptr, AsyncUpdateSlideshow_Impl, Update), pNew); + // coverity[leaked_storage] - pDisruptor takes care of its own destruction at idle time + } + + DECL_STATIC_LINK(AsyncUpdateSlideshow_Impl, Update, void*, void); + }; + + IMPL_STATIC_LINK(AsyncUpdateSlideshow_Impl, Update, void*, pData, void) + { + AsyncUpdateSlideshowData* pSlideData(static_cast<AsyncUpdateSlideshowData*>(pData)); + pSlideData->pSlideshowImpl->gotoSlide(pSlideData->XCurrentSlide); + delete pSlideData; + } +} + +void SlideshowImpl::Notify(SfxBroadcaster& /*rBC*/, const SfxHint& rHint) +{ + if (SfxHintId::ThisIsAnSdrHint != rHint.GetId()) + // nothing to do for non-SdrHints + return; + + if (nullptr == mpDoc) + // better do nothing when no DrawModel (should not happen) + return; + + const SdrHintKind eHintKind(static_cast<const SdrHint&>(rHint).GetKind()); + + if (SdrHintKind::ObjectChange == eHintKind) + { + // Object changed, object & involved page included in rHint. + uno::Reference< css::drawing::XDrawPage > XCurrentSlide(getCurrentSlide()); + if (!XCurrentSlide.is()) + return; + + SdrPage* pCurrentSlide(GetSdrPageFromXDrawPage(XCurrentSlide)); + if (nullptr == pCurrentSlide) + return; + + const SdrPage* pHintPage(static_cast<const SdrHint&>(rHint).GetPage()); + if (nullptr == pHintPage) + return; + + bool bCurrentSlideIsInvolved(false); + + if (pHintPage->IsMasterPage()) + { + if (pCurrentSlide->TRG_HasMasterPage()) + { + // current slide uses MasterPage on which the change happened + bCurrentSlideIsInvolved = (pHintPage == &pCurrentSlide->TRG_GetMasterPage()); + } + } + else + { + // object on current slide was changed + bCurrentSlideIsInvolved = (pHintPage == pCurrentSlide); + } + + if (!bCurrentSlideIsInvolved) + // nothing to do when current slide is not involved + return; + + // Refresh current slide. Need to do that asynchronous, else e.g. + // text edit changes EditEngine/Outliner are not progressed far + // enough (ObjectChanged broadcast which we are in here seems + // to early for some cases) + AsyncUpdateSlideshow_Impl::AsyncUpdateSlideshow(this, XCurrentSlide); + } + else if (SdrHintKind::PageOrderChange == eHintKind) + { + // order of pages (object pages or master pages) changed (Insert/Remove/ChangePos) + // probably needs refresh of AnimationSlideController in mpSlideController + gotoFirstSlide(); + } + + // maybe need to add reactions here to other Hint-Types +} + Reference< XSlideShow > SAL_CALL SlideshowImpl::getSlideShow() { return mxShow; diff --git a/sd/source/ui/slideshow/slideshowimpl.hxx b/sd/source/ui/slideshow/slideshowimpl.hxx index 48802ba54499..b235a78358f0 100644 --- a/sd/source/ui/slideshow/slideshowimpl.hxx +++ b/sd/source/ui/slideshow/slideshowimpl.hxx @@ -127,7 +127,7 @@ private: typedef comphelper::WeakComponentImplHelper< css::presentation::XSlideShowController, css::container::XIndexAccess > SlideshowImplBase; -class SlideshowImpl final : public SlideshowImplBase +class SlideshowImpl final : public SlideshowImplBase, public SfxListener { friend class SlideShow; friend class SlideShowView; @@ -183,6 +183,9 @@ public: virtual css::uno::Type SAL_CALL getElementType( ) override; virtual sal_Bool SAL_CALL hasElements( ) override; + // SfxListener + virtual void Notify(SfxBroadcaster& rBC, const SfxHint& rHint) override; + // will be called from the SlideShowListenerProxy when this event is fired from the XSlideShow void slideEnded(const bool bReverse); void contextMenuShow(const css::awt::Point& point);