From eda624641b34a7d4315388c8ec1aebe44f63982e Mon Sep 17 00:00:00 2001 From: Bjoern Michaelsen Date: Sun, 18 May 2014 14:28:39 +0200 Subject: [PATCH] lp#1296715: refresh invalidated menus - so we need to be a StatusListener in framework after all - we ware updating all menus for now, instead of just one - this would have a hugh performance hit when there is much change to the menu - thus we just invalidate the menu and update with all changes after 100ms once Change-Id: I48cda968cf0ae1eae0421b3424bb3e5830817e84 --- framework/source/uielement/menubarmanager.cxx | 7 ++- include/vcl/helper.hxx | 3 ++ include/vcl/menu.hxx | 11 +++++ vcl/source/window/menu.cxx | 17 ++++++++ vcl/unx/gtk/window/gtksalmenu.cxx | 43 +++++++++++++++++++ 5 files changed, 80 insertions(+), 1 deletion(-) diff --git a/framework/source/uielement/menubarmanager.cxx b/framework/source/uielement/menubarmanager.cxx index de31c3c005ea..341225135ee2 100644 --- a/framework/source/uielement/menubarmanager.cxx +++ b/framework/source/uielement/menubarmanager.cxx @@ -67,6 +67,7 @@ #include #include #include +#include #include #include #include @@ -429,6 +430,10 @@ throw ( RuntimeException, std::exception ) OUString aFeatureURL = Event.FeatureURL.Complete; SolarMutexGuard aSolarGuard; + { + vcl::MenuInvalidator aInvalidator; + aInvalidator.Invalidated(); + } { if ( m_bDisposed ) return; @@ -914,9 +919,9 @@ IMPL_LINK( MenuBarManager, Activate, Menu *, pMenu ) if ( !bPopupMenu ) { - // We need only an update to reflect the current state xMenuItemDispatch->addStatusListener( static_cast< XStatusListener* >( this ), aTargetURL ); xMenuItemDispatch->removeStatusListener( static_cast< XStatusListener* >( this ), aTargetURL ); + xMenuItemDispatch->addStatusListener( static_cast< XStatusListener* >( this ), aTargetURL ); } } else if ( !bPopupMenu ) diff --git a/include/vcl/helper.hxx b/include/vcl/helper.hxx index cc368dd4b0da..49c4197958a2 100644 --- a/include/vcl/helper.hxx +++ b/include/vcl/helper.hxx @@ -23,6 +23,7 @@ #include #include +#include #include @@ -54,6 +55,8 @@ enum whichOfficePath { InstallationRootPath, UserPath, ConfigPath }; OUString VCL_DLLPUBLIC getOfficePath( enum whichOfficePath ePath ); } // namespace + +bool VCL_DLLPUBLIC GetMenuInvalidateListeners(); #endif // INCLUDED_VCL_HELPER_HXX /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/vcl/menu.hxx b/include/vcl/menu.hxx index 9f31b20421cf..ac3c84ba0761 100644 --- a/include/vcl/menu.hxx +++ b/include/vcl/menu.hxx @@ -359,6 +359,17 @@ public: }; +namespace vcl +{ + class VCL_DLLPUBLIC MenuInvalidator + { + public: + MenuInvalidator(); + VclEventListeners2* GetMenuInvalidateListeners(); + void Invalidated(); + }; +} + // - MenuBar - diff --git a/vcl/source/window/menu.cxx b/vcl/source/window/menu.cxx index 9a7e73b6d27b..73e566803b5e 100644 --- a/vcl/source/window/menu.cxx +++ b/vcl/source/window/menu.cxx @@ -6130,4 +6130,21 @@ ImplMenuDelData::~ImplMenuDelData() const_cast< Menu* >( mpMenu )->ImplRemoveDel( *this ); } +namespace vcl +{ + MenuInvalidator::MenuInvalidator() {}; + + static VclEventListeners2* pMenuInvalidateListeners = NULL; + VclEventListeners2* MenuInvalidator::GetMenuInvalidateListeners() + { + if(!pMenuInvalidateListeners) + pMenuInvalidateListeners = new VclEventListeners2(); + return pMenuInvalidateListeners; + } + void MenuInvalidator::Invalidated() + { + VclSimpleEvent aEvent(0); + GetMenuInvalidateListeners()->callListeners(&aEvent); + }; +} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/gtk/window/gtksalmenu.cxx b/vcl/unx/gtk/window/gtksalmenu.cxx index 6143e6c72101..dcbcd78425c6 100644 --- a/vcl/unx/gtk/window/gtksalmenu.cxx +++ b/vcl/unx/gtk/window/gtksalmenu.cxx @@ -11,6 +11,8 @@ #ifdef ENABLE_GMENU_INTEGRATION +#include +#include #include #include #include @@ -448,9 +450,50 @@ void GtkSalMenu::SetSubMenu( SalMenuItem* pSalMenuItem, SalMenu* pSubMenu, unsig pItem->mpSubMenu = pGtkSubMenu; } +static bool bInvalidMenus = false; +static gboolean RefreshMenusUnity(gpointer) +{ + SalDisplay* pSalDisplay = GetGenericData()->GetSalDisplay(); + std::list< SalFrame* >::const_iterator pSalFrame = pSalDisplay->getFrames().begin(); + std::list< SalFrame* >::const_iterator pEndSalFrame = pSalDisplay->getFrames().end(); + for(; pSalFrame != pEndSalFrame; ++pSalFrame) { + const GtkSalFrame* pGtkSalFrame = static_cast< const GtkSalFrame* >( *pSalFrame ); + GtkSalFrame* pFrameNonConst = const_cast(pGtkSalFrame); + GtkSalMenu* pSalMenu = static_cast(pFrameNonConst->GetMenu()); + if(pSalMenu) { + pSalMenu->Activate(); + pSalMenu->UpdateFull(); + } + } + bInvalidMenus = false; + return FALSE; +} + +static long RefreshMenusUnity(void*, void*) +{ + if(!bInvalidMenus) { + g_timeout_add(10, &RefreshMenusUnity, NULL); + bInvalidMenus = true; + } + return 0; +} + +static Link* getRefreshLinkInstance() +{ + static Link* pLink = NULL; + if(!pLink) { + pLink = new Link(NULL, &RefreshMenusUnity); + } + return pLink; +} + void GtkSalMenu::SetFrame( const SalFrame* pFrame ) { SolarMutexGuard aGuard; + { + vcl::MenuInvalidator aInvalidator; + aInvalidator.GetMenuInvalidateListeners()->addListener(*getRefreshLinkInstance()); + } assert(mbMenuBar); SAL_INFO("vcl.unity", "GtkSalMenu set to frame");