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

New commits:
commit 8320568b4a069ce8549b76a641271333afa3cc26
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Wed Jan 29 20:43:58 2025 +0500
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Thu Jan 30 09:55:16 2025 +0500

    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

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 7175e702d709..565d1b6d9433 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>
@@ -42,6 +45,7 @@
 #include <vcl/graphicfilter.hxx>
 #include <comphelper/sequenceashashmap.hxx>
 #include <comphelper/processfactory.hxx>
+#include <cppuhelper/compbase.hxx>
 
 #include <wrtsh.hxx>
 #include <ndtxt.hxx>
@@ -1249,6 +1253,106 @@ CPPUNIT_TEST_FIXTURE(SwUnoWriter, testTdf161035)
     CPPUNIT_ASSERT(!xRunEnum->hasMoreElements()); // Empty enumeration for 
empty selection
 }
 
+CPPUNIT_TEST_FIXTURE(SwUnoWriter, testTdf164885)
+{
+    class LocalDispatch : public cppu::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 
cppu::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);
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/wrtsh/wrtsh2.cxx 
b/sw/source/uibase/wrtsh/wrtsh2.cxx
index 3a9e51136fd0..946e651526f3 100644
--- a/sw/source/uibase/wrtsh/wrtsh2.cxx
+++ b/sw/source/uibase/wrtsh/wrtsh2.cxx
@@ -597,15 +597,16 @@ static void LoadURL(SwView& rView, const OUString& rURL, 
LoadUrlFlags nFilter,
     if ((nFilter & LoadUrlFlags::NewView) && 
!comphelper::LibreOfficeKit::isActive())
         aTargetFrameName.SetValue( "_blank" );
 
-    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