sfx2/source/doc/objstor.cxx | 49 +++++++++++++++++++++++------------------ sfx2/source/view/lokhelper.cxx | 21 +++++++++++++++++ 2 files changed, 49 insertions(+), 21 deletions(-)
New commits: commit 780d6e931b21af9e29245d83d6cc232f47ea4124 Author: Caolán McNamara <[email protected]> AuthorDate: Wed Nov 5 10:57:28 2025 +0000 Commit: Caolán McNamara <[email protected]> CommitDate: Thu Nov 6 16:05:22 2025 +0100 assert on creating a new view that there is an XInteractionHandler we install one when we create a document, so detect if that was removed by something, which has happened historically on save, or export of a selected element, but we want the original XInteractionHandler to be restored when those complete. Change-Id: I0886dd038a9167fd1b53e0b382fd52e6cb8a7610 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/193465 Tested-by: Jenkins Reviewed-by: Caolán McNamara <[email protected]> diff --git a/sfx2/source/view/lokhelper.cxx b/sfx2/source/view/lokhelper.cxx index 261463deb594..d6b103715d09 100644 --- a/sfx2/source/view/lokhelper.cxx +++ b/sfx2/source/view/lokhelper.cxx @@ -36,6 +36,7 @@ #include <vcl/window.hxx> #include <sal/log.hxx> #include <sfx2/app.hxx> +#include <sfx2/docfile.hxx> #include <sfx2/msg.hxx> #include <sfx2/viewsh.hxx> #include <sfx2/request.hxx> @@ -100,10 +101,30 @@ const std::size_t g_logNotifierCacheMaxSize = 50; ::std::list<::std::string> g_logNotifierCache; } +#if !defined NDEBUG +static bool isSfxMediumMissingInteractionHandled(SfxViewFrame& rViewFrame) +{ + const SfxObjectShell* pObjSh = rViewFrame.GetObjectShell(); + const SfxMedium* pMed = pObjSh ? pObjSh->GetMedium() : nullptr; + if (!pMed) + { + // In this unlikely case it's not going to matter. + return false; + } + const SfxUnoAnyItem *pItem = pMed->GetItemSet().GetItemIfSet(SID_INTERACTIONHANDLER, false); + return !pItem || !pItem->GetValue().hasValue(); +} +#endif + int SfxLokHelper::createView(SfxViewFrame& rViewFrame, ViewShellDocId docId) { assert(docId >= ViewShellDocId(0) && "Cannot createView for invalid (negative) DocId."); + // The XInteractionHandler installed during the original lo_documentLoad + // should still be present when new views are created. If it is not + // something has likely cleared the original SID_INTERACTIONHANDLER + assert(!isSfxMediumMissingInteractionHandled(rViewFrame) && "original XInteractionHandler missing"); + SfxViewShell::SetCurrentDocId(docId); SfxRequest aRequest(rViewFrame, SID_NEWWINDOW); rViewFrame.ExecView_Impl(aRequest); commit 2d4911e8c6a368555b409c62f47d85e41927407e Author: Caolán McNamara <[email protected]> AuthorDate: Wed Nov 5 09:32:00 2025 +0000 Commit: Caolán McNamara <[email protected]> CommitDate: Thu Nov 6 16:05:14 2025 +0100 always restore original interaction handler after dosave this is similar to: commit a2007364e77aebbbc45fa8fab2c58f95a821dd18 Date: Thu May 16 14:37:52 2024 +0100 always restore existing interaction handler after save except for this other save-alike case which is used to export elements of the document Change-Id: I7da6ddde2503364274ac1292f92a7666b3afaced Reviewed-on: https://gerrit.libreoffice.org/c/core/+/193464 Tested-by: Caolán McNamara <[email protected]> Reviewed-by: Caolán McNamara <[email protected]> diff --git a/sfx2/source/doc/objstor.cxx b/sfx2/source/doc/objstor.cxx index 51e6cb8a605f..9bc7e7b78f33 100644 --- a/sfx2/source/doc/objstor.cxx +++ b/sfx2/source/doc/objstor.cxx @@ -2989,6 +2989,20 @@ bool SfxObjectShell::ConvertTo return false; } +static Any getItemSetInteractionHandler(const SfxItemSet& rItemSet) +{ + if (const SfxUnoAnyItem *pItem = rItemSet.GetItemIfSet(SID_INTERACTIONHANDLER, false)) + return pItem->GetValue(); + return Any(); +} + +static void setItemSetInteractionHandler(SfxItemSet& rItemSet, const Any& rOriginalInteract) +{ + if (rOriginalInteract.hasValue()) + rItemSet.Put(SfxUnoAnyItem(SID_INTERACTIONHANDLER, rOriginalInteract)); + else + rItemSet.ClearItem(SID_INTERACTIONHANDLER); +} bool SfxObjectShell::DoSave_Impl( const SfxItemSet* pArgs ) { @@ -3032,16 +3046,9 @@ bool SfxObjectShell::DoSave_Impl( const SfxItemSet* pArgs ) pMediumTmp->TransferVersionList_Impl( *pRetrMedium ); // Save the original interaction handler - Any aOriginalInteract; - if (const SfxUnoAnyItem *pItem = pRetrMedium->GetItemSet().GetItemIfSet(SID_INTERACTIONHANDLER, false)) - { - aOriginalInteract = pItem->GetValue(); -#ifndef NDEBUG - // The original pRetrMedium and potential replacement pMediumTmp have the same interaction handler at this point - const SfxUnoAnyItem *pMediumItem = pMediumTmp->GetItemSet().GetItemIfSet(SID_INTERACTIONHANDLER, false); - assert(pMediumItem && pMediumItem->GetValue() == aOriginalInteract); -#endif - } + Any aOriginalInteract = getItemSetInteractionHandler(pRetrMedium->GetItemSet()); + // The original pRetrMedium and potential replacement pMediumTmp have the same interaction handler at this point + assert(getItemSetInteractionHandler(pMediumTmp->GetItemSet()) == aOriginalInteract); // an interaction handler here can acquire only in case of GUI Saving // and should be removed after the saving is done @@ -3059,10 +3066,7 @@ bool SfxObjectShell::DoSave_Impl( const SfxItemSet* pArgs ) { bSaved = true; - if (aOriginalInteract.hasValue()) - pMediumTmp->GetItemSet().Put(SfxUnoAnyItem(SID_INTERACTIONHANDLER, aOriginalInteract)); - else - pMediumTmp->GetItemSet().ClearItem(SID_INTERACTIONHANDLER); + setItemSetInteractionHandler(pMediumTmp->GetItemSet(), aOriginalInteract); pMediumTmp->GetItemSet().ClearItem( SID_PROGRESS_STATUSBAR_CONTROL ); SetError(pMediumTmp->GetErrorCode()); @@ -3088,10 +3092,7 @@ bool SfxObjectShell::DoSave_Impl( const SfxItemSet* pArgs ) // reconnect to object storage DoSaveCompleted(); - if (aOriginalInteract.hasValue()) - pRetrMedium->GetItemSet().Put(SfxUnoAnyItem(SID_INTERACTIONHANDLER, aOriginalInteract)); - else - pRetrMedium->GetItemSet().ClearItem(SID_INTERACTIONHANDLER); + setItemSetInteractionHandler(pRetrMedium->GetItemSet(), aOriginalInteract); pRetrMedium->GetItemSet().ClearItem( SID_PROGRESS_STATUSBAR_CONTROL ); delete pMediumTmp; @@ -3217,12 +3218,18 @@ bool SfxObjectShell::CommonSaveAs_Impl(const INetURLObject& aURL, const OUString aTempFileURL = pMedium->GetURLObject().GetMainURL( INetURLObject::DecodeMechanism::NONE ); #endif - if (PreDoSaveAs_Impl(aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE), aFilterName, - rItemSet, rArgs)) + // Save the original interaction handler + Any aOriginalInteract = getItemSetInteractionHandler(GetMedium()->GetItemSet()); + + bool bResult = PreDoSaveAs_Impl(aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE), aFilterName, + rItemSet, rArgs); + + setItemSetInteractionHandler(GetMedium()->GetItemSet(), aOriginalInteract); + + if (bResult) { // Update Data on media SfxItemSet& rSet = GetMedium()->GetItemSet(); - rSet.ClearItem( SID_INTERACTIONHANDLER ); rSet.ClearItem( SID_PROGRESS_STATUSBAR_CONTROL ); rSet.ClearItem( SID_PATH );
