framework/source/services/ContextChangeEventMultiplexer.cxx | 2 include/vcl/notebookbar.hxx | 7 +- sc/source/ui/view/prevwsh.cxx | 4 - sfx2/source/notebookbar/SfxNotebookBar.cxx | 15 +---- sw/source/uibase/uiview/pview.cxx | 4 - vcl/source/control/notebookbar.cxx | 32 +++++++++--- 6 files changed, 37 insertions(+), 27 deletions(-)
New commits: commit afa6a774936c34b09b37ab8539193ac529681798 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Mon Jan 6 10:49:31 2020 +0300 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Mon Jan 6 11:29:17 2020 +0100 Don't crash on exiting print preview with Notebookbar Crash caused by this sequence (tested in Writer): 1. Closing print preview, frame is attached to controller; 2. This calls SfxNotebookBar::StateMethod 3. There notebookbar's listener is added to list of the controller's context change event listeners 4. Then in SwPagePreview::~SwPagePreview, notebookbar's listener is added to that list again 5. ContextChangeEventMultiplexer::addContextChangeEventListener detects second addition, and throws an unhandled exception. I don't know why starting listening is needed in SwPagePreview dtor; unfortunately commit d05b7b32d9ecb6fcb4a268eb68cdcee09bafa6dd doesn't say much about context and reasons. ControlListener is renamed to ControlListenerForCurrentController to emphasize that it operates on the current controller of notebookbar's frame; and its bListen parameter meaning was reverted: previously its "true" value awkwardly meant "stop listening". All direct operations with listener of notebookbar are replaced with calls to notebookbar's methods. In ContextChangeEventMultiplexer::addContextChangeEventListener, uno::UNO_QUERY_THROW was replaced with uno::UNO_QUERY, because not only chart controller may appear here, and it's not an error: e.g. SfxBaseController doesn't implement lang::XServiceInfo. Regression after commit d05b7b32d9ecb6fcb4a268eb68cdcee09bafa6dd. Change-Id: Ief1aed188d8f02a6cfe3ea25f4d082dfdf449f32 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/86257 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> diff --git a/framework/source/services/ContextChangeEventMultiplexer.cxx b/framework/source/services/ContextChangeEventMultiplexer.cxx index c6da6be6b0d1..4dbc182ceaa5 100644 --- a/framework/source/services/ContextChangeEventMultiplexer.cxx +++ b/framework/source/services/ContextChangeEventMultiplexer.cxx @@ -166,7 +166,7 @@ void SAL_CALL ContextChangeEventMultiplexer::addContextChangeEventListener ( if (pFocusDescriptor->msCurrentApplicationName.isEmpty() && pFocusDescriptor->msCurrentContextName.isEmpty() && rxEventFocus.is()) { - Reference< lang::XServiceInfo > xServInfo( rxEventFocus, uno::UNO_QUERY_THROW ); + Reference< lang::XServiceInfo > xServInfo( rxEventFocus, uno::UNO_QUERY ); if( xServInfo.is() && xServInfo->getImplementationName() == "com.sun.star.comp.chart2.ChartController") { css::ui::ContextChangeEventObject aEvent ( diff --git a/include/vcl/notebookbar.hxx b/include/vcl/notebookbar.hxx index af904ca2ae5f..457a64b9a206 100644 --- a/include/vcl/notebookbar.hxx +++ b/include/vcl/notebookbar.hxx @@ -14,6 +14,7 @@ #include <vcl/ctrl.hxx> #include <vcl/NotebookBarAddonsMerger.hxx> #include <vcl/settings.hxx> +#include <set> #include <vector> namespace com { namespace sun { namespace star { namespace ui { class XContextChangeEventListener; } } } } @@ -39,17 +40,17 @@ public: void SetSystemWindow(SystemWindow* pSystemWindow); - const css::uno::Reference<css::ui::XContextChangeEventListener>& getContextChangeEventListener() const { return m_pEventListener; } - void StateChanged(const StateChangedType nStateChange ) override; void DataChanged(const DataChangedEvent& rDCEvt) override; - void ControlListener(bool bListen); + void ControlListenerForCurrentController(bool bListen); + void StopListeningAllControllers(); private: VclPtr<SystemWindow> m_pSystemWindow; css::uno::Reference<css::ui::XContextChangeEventListener> m_pEventListener; + std::set<css::uno::Reference<css::frame::XController>> m_alisteningControllers; std::vector<NotebookbarContextControl*> m_pContextContainers; css::uno::Reference<css::frame::XFrame> mxFrame; diff --git a/sc/source/ui/view/prevwsh.cxx b/sc/source/ui/view/prevwsh.cxx index 493ce87228ce..fe3688abdd43 100644 --- a/sc/source/ui/view/prevwsh.cxx +++ b/sc/source/ui/view/prevwsh.cxx @@ -160,7 +160,7 @@ ScPreviewShell::ScPreviewShell( SfxViewFrame* pViewFrame, auto& pNotebookBar = pViewFrame->GetWindow().GetSystemWindow()->GetNotebookBar(); if (pNotebookBar) - pNotebookBar->ControlListener(true); + pNotebookBar->ControlListenerForCurrentController(false); // stop listening if ( auto pTabViewShell = dynamic_cast<ScTabViewShell*>( pOldSh) ) { @@ -189,7 +189,7 @@ ScPreviewShell::~ScPreviewShell() mpFrameWindow->SetCloseHdl(Link<SystemWindow&,void>()); // Remove close handler. if (auto& pBar = GetViewFrame()->GetWindow().GetSystemWindow()->GetNotebookBar()) - pBar->ControlListener(false); + pBar->ControlListenerForCurrentController(true); // let it start listening now // #108333#; notify Accessibility that Shell is dying and before destroy all BroadcastAccessibility( SfxHint( SfxHintId::Dying ) ); diff --git a/sfx2/source/notebookbar/SfxNotebookBar.cxx b/sfx2/source/notebookbar/SfxNotebookBar.cxx index 538886f202a1..a2d7f1f39b17 100644 --- a/sfx2/source/notebookbar/SfxNotebookBar.cxx +++ b/sfx2/source/notebookbar/SfxNotebookBar.cxx @@ -400,15 +400,7 @@ bool SfxNotebookBar::StateMethod(SystemWindow* pSysWindow, if(pView) { - Reference<XContextChangeEventMultiplexer> xMultiplexer - = ContextChangeEventMultiplexer::get( xContext ); - - if(xFrame.is()) - { - xMultiplexer->addContextChangeEventListener( - pNotebookBar->getContextChangeEventListener(), - xFrame->getController()); - } + pNotebookBar->ControlListenerForCurrentController(true); } } @@ -430,10 +422,9 @@ void SfxNotebookBar::RemoveListeners(SystemWindow const * pSysWindow) = ContextChangeEventMultiplexer::get( ::comphelper::getProcessComponentContext()); - if (pSysWindow->GetNotebookBar()) + if (auto pNotebookBar = pSysWindow->GetNotebookBar()) { - xMultiplexer->removeAllContextChangeEventListeners( - pSysWindow->GetNotebookBar()->getContextChangeEventListener()); + pNotebookBar->StopListeningAllControllers(); } } diff --git a/sw/source/uibase/uiview/pview.cxx b/sw/source/uibase/uiview/pview.cxx index 89014a5841ab..2ab2568d1f76 100644 --- a/sw/source/uibase/uiview/pview.cxx +++ b/sw/source/uibase/uiview/pview.cxx @@ -1165,7 +1165,7 @@ SwPagePreview::SwPagePreview(SfxViewFrame *pViewFrame, SfxViewShell* pOldSh): SfxShell::BroadcastContextForActivation(true); //removelisteners for notebookbar if (auto& pBar = SfxViewFrame::Current()->GetWindow().GetSystemWindow()->GetNotebookBar()) - pBar->ControlListener(true); + pBar->ControlListenerForCurrentController(false); SfxObjectShell* pObjShell = pViewFrame->GetObjectShell(); if ( !pOldSh ) @@ -1233,7 +1233,7 @@ SwPagePreview::~SwPagePreview() m_pViewWin.disposeAndClear(); if (SfxViewFrame* pCurrent = SfxViewFrame::Current()) if (auto& pBar = pCurrent->GetWindow().GetSystemWindow()->GetNotebookBar()) - pBar->ControlListener(false); + pBar->ControlListenerForCurrentController(true); // start listening now m_pScrollFill.disposeAndClear(); m_pHScrollbar.disposeAndClear(); m_pVScrollbar.disposeAndClear(); diff --git a/vcl/source/control/notebookbar.cxx b/vcl/source/control/notebookbar.cxx index 6ddc1c662c91..08f82b49a772 100644 --- a/vcl/source/control/notebookbar.cxx +++ b/vcl/source/control/notebookbar.cxx @@ -97,6 +97,7 @@ void NotebookBar::dispose() m_pSystemWindow->GetTaskPaneList()->RemoveWindow(this); m_pSystemWindow.clear(); disposeBuilder(); + assert(m_alisteningControllers.empty()); m_pEventListener.clear(); Control::dispose(); } @@ -180,24 +181,41 @@ void SAL_CALL NotebookBarContextChangeEventListener::notifyContextChangeEvent(co } } -void NotebookBar::ControlListener(bool bListen) +void NotebookBar::ControlListenerForCurrentController(bool bListen) { + auto xController = mxFrame->getController(); if(bListen) { - // remove listeners - css::uno::Reference<css::ui::XContextChangeEventMultiplexer> xMultiplexer (css::ui::ContextChangeEventMultiplexer::get( + // add listeners + if (m_alisteningControllers.count(xController) == 0) + { + auto xMultiplexer(css::ui::ContextChangeEventMultiplexer::get( ::comphelper::getProcessComponentContext())); - xMultiplexer->removeContextChangeEventListener(getContextChangeEventListener(),mxFrame->getController()); + xMultiplexer->addContextChangeEventListener(m_pEventListener, xController); + m_alisteningControllers.insert(xController); + } } else { - // add listeners - css::uno::Reference<css::ui::XContextChangeEventMultiplexer> xMultiplexer (css::ui::ContextChangeEventMultiplexer::get( + // remove listeners + if (m_alisteningControllers.count(xController)) + { + auto xMultiplexer(css::ui::ContextChangeEventMultiplexer::get( ::comphelper::getProcessComponentContext())); - xMultiplexer->addContextChangeEventListener(getContextChangeEventListener(),mxFrame->getController()); + xMultiplexer->removeContextChangeEventListener(m_pEventListener, xController); + m_alisteningControllers.erase(xController); + } } } +void NotebookBar::StopListeningAllControllers() +{ + auto xMultiplexer( + css::ui::ContextChangeEventMultiplexer::get(comphelper::getProcessComponentContext())); + xMultiplexer->removeAllContextChangeEventListeners(m_pEventListener); + m_alisteningControllers.clear(); +} + void SAL_CALL NotebookBarContextChangeEventListener::disposing(const ::css::lang::EventObject&) { mpParent.clear(); _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits