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 );
 

Reply via email to