framework/source/uielement/menubarmanager.cxx |   41 +++++++++++++++++---------
 1 file changed, 28 insertions(+), 13 deletions(-)

New commits:
commit e931c4e9399ba96054ed153204627579242a5cc6
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Fri Jun 13 21:44:21 2025 +0500
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Sat Jun 14 08:41:13 2025 +0200

    tdf#166996: handle menu commands asynchronously
    
    Instead of doing that command by command, this change tries to do it
    globally, posting user event with the command data; it will run when
    event loop gets to it; the menu gets closed by that time.
    
    Change-Id: Ifdea666be8557a576dd6cd934898343631a3a95e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/186470
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/framework/source/uielement/menubarmanager.cxx 
b/framework/source/uielement/menubarmanager.cxx
index caa0aaa36ce3..f740121f386c 100644
--- a/framework/source/uielement/menubarmanager.cxx
+++ b/framework/source/uielement/menubarmanager.cxx
@@ -773,11 +773,29 @@ IMPL_LINK_NOARG( MenuBarManager, AsyncSettingsHdl, 
Timer*, void)
     }
 }
 
-IMPL_LINK( MenuBarManager, Select, Menu *, pMenu, bool )
+namespace
+{
+struct MenuExecData
 {
-    URL                     aTargetURL;
+    URL aTargetURL;
     std::vector<beans::PropertyValue> aArgs;
-    Reference< XDispatch >  xDispatch;
+    Reference<XDispatch> xDispatch;
+};
+
+void AsyncMenuExecute(void* /*instance*/, void* data)
+{
+    std::unique_ptr<MenuExecData> pData(static_cast<MenuExecData*>(data));
+    {
+        SolarMutexReleaser aReleaser;
+        pData->xDispatch->dispatch(pData->aTargetURL,
+                                   
comphelper::containerToSequence(pData->aArgs));
+    }
+}
+}
+
+IMPL_LINK( MenuBarManager, Select, Menu *, pMenu, bool )
+{
+    auto pData = std::make_unique<MenuExecData>();
 
     {
         SolarMutexGuard g;
@@ -790,13 +808,13 @@ IMPL_LINK( MenuBarManager, Select, Menu *, pMenu, bool )
             MenuItemHandler* pMenuItemHandler = GetMenuItemHandler( nCurItemId 
);
             if ( pMenuItemHandler && pMenuItemHandler->xMenuItemDispatch.is() )
             {
-                aTargetURL.Complete = pMenuItemHandler->aMenuItemURL;
-                m_xURLTransformer->parseStrict( aTargetURL );
+                pData->aTargetURL.Complete = pMenuItemHandler->aMenuItemURL;
+                m_xURLTransformer->parseStrict( pData->aTargetURL );
 
                 if ( pMenu->GetUserValue( nCurItemId ) )
                 {
                     // addon menu item selected
-                    aArgs.push_back(
+                    pData->aArgs.push_back(
                         comphelper::makePropertyValue(u"Referer"_ustr, 
u"private:user"_ustr));
                 }
 
@@ -806,19 +824,16 @@ IMPL_LINK( MenuBarManager, Select, Menu *, pMenu, bool )
                 const sal_Int16 nKeys
                     = pWindow ? pWindow->GetPointerState().mnState & 
KEY_MODIFIERS_MASK : 0;
                 if (nKeys)
-                    
aArgs.push_back(comphelper::makePropertyValue(u"KeyModifier"_ustr, nKeys));
+                    
pData->aArgs.push_back(comphelper::makePropertyValue(u"KeyModifier"_ustr, 
nKeys));
 
-                xDispatch = pMenuItemHandler->xMenuItemDispatch;
+                pData->xDispatch = pMenuItemHandler->xMenuItemDispatch;
             }
         }
     }
 
-    // tdf#126054 don't let dispatch destroy this until after function 
completes
-    rtl::Reference<MenuBarManager> xKeepAlive(this);
-    if (xDispatch.is())
+    if (pData->xDispatch.is())
     {
-        SolarMutexReleaser aReleaser;
-        xDispatch->dispatch(aTargetURL, 
comphelper::containerToSequence(aArgs));
+        Application::PostUserEvent(LINK_NONMEMBER(nullptr, AsyncMenuExecute), 
pData.release());
     }
 
     if ( !m_bHasMenuBar )

Reply via email to