diff options
Diffstat (limited to 'sfx2/source/control/dispatch.cxx')
-rw-r--r-- | sfx2/source/control/dispatch.cxx | 94 |
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 |