sw/qa/extras/unowriter/data/hyperlink.fodt |    9 ++
 sw/qa/extras/unowriter/unowriter.cxx       |  105 +++++++++++++++++++++++++++++
 sw/source/uibase/wrtsh/wrtsh2.cxx          |   11 +--
 3 files changed, 120 insertions(+), 5 deletions(-)

New commits:
commit c8ffdd69d7d989ac3920d8a580c5a678f0075052
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Wed Jan 29 20:43:58 2025 +0500
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Wed Feb 5 21:20:41 2025 +0100

    tdf#164885: use SfxBindings::Execute instead of SfxDispatcher::ExecuteList
    
    Commit 502f7958d99e3aa27f4c1c1f33f4827055459da8 (pass a frame to use as
    parent for any dialog that may need to appear, 2023-11-16) switched to
    SfxDispatcher::ExecuteList, in order to pass there frame to be used as
    parent for dialogs.
    
    Later, in commit d7b33b1be8fee684e906f170f4001735c095056e (use SID_DOCFRAME
    for dialog parents if there is no SID_FILLFRAME, 2023-11-23), the fix
    was changed, and passing the frame got not needed.
    
    Since the change to SfxDispatcher::ExecuteList caused the regression
    (likely because SfxDispatcher unexpectedly uses a bit different method
    to find the slot server), and the original reason for the change is no
    more actual, let's revert to the older method.
    
    Change-Id: I6b126bf336dcf8cd3f49a3ce9682f3adc3bc208f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180909
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    Tested-by: Jenkins
    (cherry picked from commit 0e9785ef0a3f0c350f8e719d2062f1c7beb801ad)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180922
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>
    (cherry picked from commit 339f3173e09434fdc49046cc2277b864167dedd3)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180930
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/sw/qa/extras/unowriter/data/hyperlink.fodt 
b/sw/qa/extras/unowriter/data/hyperlink.fodt
new file mode 100644
index 000000000000..d3d73c750d15
--- /dev/null
+++ b/sw/qa/extras/unowriter/data/hyperlink.fodt
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
xmlns:xlink="http://www.w3.org/1999/xlink"; 
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" 
office:version="1.4" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:body>
+  <office:text>
+   <text:p>A <text:a xlink:type="simple" 
xlink:href="https://www.libreoffice.org/"; text:style-name="Internet_20_link" 
text:visited-style-name="Visited_20_Internet_20_Link">hyperlink</text:a> 
here.</text:p>
+  </office:text>
+ </office:body>
+</office:document>
\ No newline at end of file
diff --git a/sw/qa/extras/unowriter/unowriter.cxx 
b/sw/qa/extras/unowriter/unowriter.cxx
index f39448455bbf..0f2a9f3ed121 100644
--- a/sw/qa/extras/unowriter/unowriter.cxx
+++ b/sw/qa/extras/unowriter/unowriter.cxx
@@ -12,6 +12,9 @@
 #include <com/sun/star/awt/FontSlant.hpp>
 #include <com/sun/star/datatransfer/XTransferableSupplier.hpp>
 #include <com/sun/star/datatransfer/XTransferableTextSupplier.hpp>
+#include <com/sun/star/frame/XDispatch.hpp>
+#include <com/sun/star/frame/XDispatchProviderInterception.hpp>
+#include <com/sun/star/frame/XDispatchProviderInterceptor.hpp>
 #include <com/sun/star/table/XCellRange.hpp>
 #include <com/sun/star/text/TextContentAnchorType.hpp>
 #include <com/sun/star/text/AutoTextContainer.hpp>
@@ -43,6 +46,7 @@
 #include <comphelper/sequenceashashmap.hxx>
 #include <comphelper/processfactory.hxx>
 #include <comphelper/propertysequence.hxx>
+#include <comphelper/compbase.hxx>
 
 #include <wrtsh.hxx>
 #include <ndtxt.hxx>
@@ -1330,6 +1334,107 @@ CPPUNIT_TEST_FIXTURE(SwUnoWriter, testTdf162480)
     CPPUNIT_ASSERT_EQUAL(xCellText, xAnchorRange->getText());
 }
 
+CPPUNIT_TEST_FIXTURE(SwUnoWriter, testTdf164885)
+{
+    class LocalDispatch : public 
comphelper::WeakImplHelper<css::frame::XDispatch>
+    {
+    public:
+        LocalDispatch() = default;
+
+        void SAL_CALL dispatch(const css::util::URL& URL,
+                               const 
css::uno::Sequence<css::beans::PropertyValue>&) override
+        {
+            sLastCommand = URL.Complete;
+        }
+        void SAL_CALL addStatusListener(const 
css::uno::Reference<css::frame::XStatusListener>&,
+                                        const css::util::URL&) override
+        {
+            // empty
+        }
+        void SAL_CALL removeStatusListener(const 
css::uno::Reference<css::frame::XStatusListener>&,
+                                           const css::util::URL&) override
+        {
+            // empty
+        }
+
+        OUString sLastCommand;
+    };
+
+    class LocalInterceptor
+        : public 
comphelper::WeakImplHelper<css::frame::XDispatchProviderInterceptor>
+    {
+    public:
+        LocalInterceptor() = default;
+
+        // XDispatchProvider
+        css::uno::Reference<css::frame::XDispatch>
+            SAL_CALL queryDispatch(const css::util::URL& URL, const OUString& 
TargetFrameName,
+                                   sal_Int32 SearchFlags) override
+        {
+            if (URL.Complete == ".uno:Open")
+                return pDispatch;
+            if (m_slave)
+                return m_slave->queryDispatch(URL, TargetFrameName, 
SearchFlags);
+            return {};
+        }
+        css::uno::Sequence<css::uno::Reference<css::frame::XDispatch>> SAL_CALL
+        queryDispatches(const 
css::uno::Sequence<css::frame::DispatchDescriptor>&) override
+        {
+            return {};
+        }
+
+        // XDispatchProviderInterceptor
+        css::uno::Reference<css::frame::XDispatchProvider>
+            SAL_CALL getSlaveDispatchProvider() override
+        {
+            return m_slave;
+        }
+        void SAL_CALL setSlaveDispatchProvider(
+            const css::uno::Reference<css::frame::XDispatchProvider>& val) 
override
+        {
+            m_slave = val;
+        }
+        css::uno::Reference<css::frame::XDispatchProvider>
+            SAL_CALL getMasterDispatchProvider() override
+        {
+            return m_master;
+        }
+        void SAL_CALL setMasterDispatchProvider(
+            const css::uno::Reference<css::frame::XDispatchProvider>& val) 
override
+        {
+            m_master = val;
+        }
+
+        rtl::Reference<LocalDispatch> pDispatch{ new LocalDispatch };
+
+    private:
+        css::uno::Reference<css::frame::XDispatchProvider> m_master;
+        css::uno::Reference<css::frame::XDispatchProvider> m_slave;
+    };
+
+    // Given a document with a hyperlink
+    createSwDoc("hyperlink.fodt");
+    auto 
controller(mxComponent.queryThrow<frame::XModel>()->getCurrentController());
+    auto 
xProvider(controller->getFrame().queryThrow<css::frame::XDispatchProviderInterception>());
+
+    rtl::Reference<LocalInterceptor> interceptor(new LocalInterceptor);
+    xProvider->registerDispatchProviderInterceptor(interceptor);
+
+    auto xCursor = 
controller.queryThrow<text::XTextViewCursorSupplier>()->getViewCursor();
+    xCursor->goRight(5, false); // put cursor inside the hyperlink
+
+    // Initiale "open hyperlink"
+    dispatchCommand(mxComponent, u".uno:OpenHyperlinkOnCursor"_ustr, {});
+
+    xProvider->releaseDispatchProviderInterceptor(interceptor);
+
+    // Without the fix, this failed with
+    // - Expected: .uno:Open
+    // - Actual  :
+    // because the interception didn't happen
+    CPPUNIT_ASSERT_EQUAL(u".uno:Open"_ustr, 
interceptor->pDispatch->sLastCommand);
+}
+
 } // end of anonymous namespace
 CPPUNIT_PLUGIN_IMPLEMENT();
 
diff --git a/sw/source/uibase/wrtsh/wrtsh2.cxx 
b/sw/source/uibase/wrtsh/wrtsh2.cxx
index 780a7352ac9d..1205da241205 100644
--- a/sw/source/uibase/wrtsh/wrtsh2.cxx
+++ b/sw/source/uibase/wrtsh/wrtsh2.cxx
@@ -602,15 +602,16 @@ static void LoadURL(SwView& rView, const OUString& rURL, 
LoadUrlFlags nFilter,
     if ((nFilter & LoadUrlFlags::NewView) && 
!comphelper::LibreOfficeKit::isActive())
         aTargetFrameName.SetValue( u"_blank"_ustr );
 
-    rViewFrame.GetDispatcher()->ExecuteList(SID_OPENDOC,
-            SfxCallMode::ASYNCHRON|SfxCallMode::RECORD,
-            {
+    const SfxPoolItem* aArr[] = {
                 &aName,
                 &aNewView, /*&aSilent,*/
                 &aReferer,
                 &aView, &aTargetFrameName,
-                &aBrowse
-            });
+                &aBrowse,
+                nullptr
+            };
+    rViewFrame.GetDispatcher()->GetBindings()->Execute(
+        SID_OPENDOC, aArr, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD);
 }
 
 void LoadURL( SwViewShell& rVSh, const OUString& rURL, LoadUrlFlags nFilter,

Reply via email to