summaryrefslogtreecommitdiff
path: root/sfx2/source/control/dispatch.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sfx2/source/control/dispatch.cxx')
-rw-r--r--sfx2/source/control/dispatch.cxx94
1 files changed, 83 insertions, 11 deletions
diff --git a/sfx2/source/control/dispatch.cxx b/sfx2/source/control/dispatch.cxx
index 6a492bffda7e..dd028723acc8 100644
--- a/sfx2/source/control/dispatch.cxx
+++ b/sfx2/source/control/dispatch.cxx
@@ -60,6 +60,7 @@
#include <svl/eitem.hxx>
#include <svl/itemiter.hxx>
#include <svl/itempool.hxx>
+#include <svtools/dialogclosedlistener.hxx>
#include <toolkit/awt/vclxmenu.hxx>
#include <toolkit/helper/vclunohelper.hxx>
#include <tools/debug.hxx>
@@ -137,8 +138,12 @@ struct SfxDispatcher_Impl
SfxDisableFlags nDisableFlags;
bool bFlushed;
std::deque< std::deque<SfxToDo_Impl> > aToDoCopyStack;
+
+ static css::uno::Reference<css::frame::XPopupMenuController>* m_pActivePopupController;
};
+css::uno::Reference<css::frame::XPopupMenuController>* SfxDispatcher_Impl::m_pActivePopupController = nullptr;
+
/** This method checks if the stack of the SfxDispatchers is flushed, or if
push- or pop- commands are pending.
*/
@@ -1713,7 +1718,52 @@ bool SfxDispatcher::FillState_(const SfxSlotServer& rSvr, SfxItemSet& rState,
return false;
}
-void SfxDispatcher::ExecutePopup( vcl::Window *pWin, const Point *pPos )
+namespace {
+
+static void lcl_FinishPopupDispatch(css::uno::Reference<css::frame::XPopupMenuController> xPopupController)
+{
+ css::uno::Reference<css::lang::XComponent> xComponent(xPopupController, css::uno::UNO_QUERY);
+ if (xComponent.is())
+ xComponent->dispose();
+ SfxDispatcher_Impl::m_pActivePopupController = nullptr;
+}
+
+struct SfxDispatcherPopupFinish final
+{
+ css::uno::Reference<css::frame::XPopupMenuController> m_xPopupController;
+ std::function<void(sal_Int16)> m_aCloseFunc;
+ rtl::Reference<::svt::DialogClosedListener> m_xDialogListener;
+ css::uno::Reference<css::awt::XPopupMenu> m_xPopupMenu;
+
+ DECL_LINK(PopupClosedHdl, css::ui::dialogs::DialogClosedEvent*, void);
+
+ SfxDispatcherPopupFinish(css::uno::Reference<css::frame::XPopupMenuController> xPopupController,
+ const std::function<void(sal_Int16)>& rCloseFunc,
+ css::uno::Reference<css::awt::XPopupMenu> xPopupMenu)
+ : m_xPopupController(xPopupController)
+ , m_aCloseFunc(rCloseFunc)
+ , m_xDialogListener(new ::svt::DialogClosedListener())
+ , m_xPopupMenu(xPopupMenu)
+ {
+ m_xDialogListener->SetDialogClosedLink(LINK(this, SfxDispatcherPopupFinish, PopupClosedHdl));
+ }
+};
+
+IMPL_LINK(SfxDispatcherPopupFinish, PopupClosedHdl, css::ui::dialogs::DialogClosedEvent*, pEvt, void)
+{
+ assert(m_xPopupController.is());
+ if (!comphelper::LibreOfficeKit::isActive())
+ assert(SfxDispatcher_Impl::m_pActivePopupController == &m_xPopupController);
+ if (m_aCloseFunc)
+ m_aCloseFunc(pEvt ? pEvt->DialogResult : 0);
+ lcl_FinishPopupDispatch(m_xPopupController);
+ delete this;
+}
+
+} // anon namespace
+
+void SfxDispatcher::ExecutePopup(vcl::Window *pWin, const Point *pPos,
+ const std::function<void(sal_Int16)>& rCloseFunc)
{
SfxDispatcher &rDisp = *SfxGetpApp()->GetDispatcher_Impl();
sal_uInt16 nShLevel = 0;
@@ -1727,7 +1777,7 @@ void SfxDispatcher::ExecutePopup( vcl::Window *pWin, const Point *pPos )
const OUString& rResName = pSh->GetInterface()->GetPopupMenuName();
if ( !rResName.isEmpty() )
{
- rDisp.ExecutePopup( rResName, pWin, pPos );
+ rDisp.ExecutePopup(rResName, pWin, pPos, rCloseFunc);
return;
}
}
@@ -1835,7 +1885,8 @@ boost::property_tree::ptree SfxDispatcher::fillPopupMenu(const rtl::Reference<VC
return ::fillPopupMenu(pVCLMenu);
}
-void SfxDispatcher::ExecutePopup( const OUString& rResName, vcl::Window* pWin, const Point* pPos )
+void SfxDispatcher::ExecutePopup( const OUString& rResName, vcl::Window* pWin, const Point* pPos,
+ const std::function<void(sal_Int16)>& rCloseFunc)
{
css::uno::Sequence< css::uno::Any > aArgs{
css::uno::Any(comphelper::makePropertyValue( "Value", rResName )),
@@ -1844,15 +1895,29 @@ void SfxDispatcher::ExecutePopup( const OUString& rResName, vcl::Window* pWin, c
};
css::uno::Reference< css::uno::XComponentContext > xContext = comphelper::getProcessComponentContext();
- css::uno::Reference< css::frame::XPopupMenuController > xPopupController(
- xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
- "com.sun.star.comp.framework.ResourceMenuController", aArgs, xContext ), css::uno::UNO_QUERY );
+
+ if (!comphelper::LibreOfficeKit::isActive())
+ assert(!xImp->m_pActivePopupController);
+ if (!comphelper::LibreOfficeKit::isActive() && xImp->m_pActivePopupController)
+ return;
+
+ css::uno::Reference<css::frame::XPopupMenuController> xPopupController =
+ css::uno::Reference<css::frame::XPopupMenuController>(
+ xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+ "com.sun.star.comp.framework.ResourceMenuController", aArgs, xContext), css::uno::UNO_QUERY);
+ if (!xPopupController.is())
+ return;
+ SfxDispatcher_Impl::m_pActivePopupController = &xPopupController;
rtl::Reference< VCLXPopupMenu > xPopupMenu = new VCLXPopupMenu();
- if ( !xPopupController.is() || !xPopupMenu.is() )
+ if ( !xPopupMenu.is() )
+ {
+ lcl_FinishPopupDispatch(xPopupController);
return;
+ }
+ struct SfxDispatcherPopupFinish* pFin = nullptr;
vcl::Window* pWindow = pWin ? pWin : xImp->pFrame->GetFrame().GetWorkWindow_Impl()->GetWindow();
Point aPos = pPos ? *pPos : pWindow->GetPointerPosPixel();
@@ -1878,14 +1943,21 @@ void SfxDispatcher::ExecutePopup( const OUString& rResName, vcl::Window* pWin, c
OUString aMenuURL = "private:resource/popupmenu/" + rResName;
if (GetFrame()->GetViewShell()->TryContextMenuInterception(xPopupMenu, aMenuURL, aEvent))
{
+ const sal_Int16 nFlags = css::awt::PopupMenuDirection::EXECUTE_DOWN;
+ const css::awt::Rectangle aRect(aPos.X(), aPos.Y(), 1, 1);
css::uno::Reference<css::awt::XWindowPeer> xParent(aEvent.SourceWindow, css::uno::UNO_QUERY);
- xPopupMenu->execute(xParent, css::awt::Rectangle(aPos.X(), aPos.Y(), 1, 1), css::awt::PopupMenuDirection::EXECUTE_DOWN);
+ pFin = new SfxDispatcherPopupFinish(xPopupController, rCloseFunc, xPopupMenu);
+ if (!rCloseFunc || !xPopupMenu->popup(xParent, aRect, nFlags, pFin->m_xDialogListener))
+ {
+ delete pFin;
+ pFin = nullptr;
+ xPopupMenu->execute(xParent, aRect, nFlags);
+ }
}
}
- css::uno::Reference< css::lang::XComponent > xComponent( xPopupController, css::uno::UNO_QUERY );
- if ( xComponent.is() )
- xComponent->dispose();
+ if (!pFin)
+ lcl_FinishPopupDispatch(xPopupController);
}
/** With this method the SfxDispatcher can be locked and released. A locked