08e5ad2
From fcab9d2bcef3997790f3ae68521444cbaa0c5b29 Mon Sep 17 00:00:00 2001
08e5ad2
From: Maxim Monastirsky <momonasmon@gmail.com>
08e5ad2
Date: Sun, 7 Feb 2016 17:53:40 +0200
08e5ad2
Subject: [PATCH] tdf#97665 Let's hope that over activation isn't really needed
08e5ad2
08e5ad2
- MenuBarManager::Activate has a check for duplicate activation,
08e5ad2
  which makes the second activation attempt fail. Removing this
08e5ad2
  check or deactivating after each activation will likely affect
08e5ad2
  performance even more, but on the other hand should solve
08e5ad2
  lp#1296715, which was the main reason of the over activation
08e5ad2
  in the first place. So let's activate only one menu at a time,
08e5ad2
  and do full activation only on the initial update.
08e5ad2
08e5ad2
- Unfortunately the HUD activation callback doesn't work, so
08e5ad2
  we still have to keep active status listener for all menu
08e5ad2
  items. (Which is BTW against the recommendation in
08e5ad2
  XPopupMenuController::updatePopupMenu IDL doc. Fortunately
08e5ad2
  the performance problem hardly noticeable on modern hw.)
08e5ad2
08e5ad2
Reviewed-on: https://gerrit.libreoffice.org/22369
08e5ad2
Tested-by: Jenkins <ci@libreoffice.org>
08e5ad2
Reviewed-by: Maxim Monastirsky <momonasmon@gmail.com>
08e5ad2
(cherry picked from commit 2abdcfd641883f246fe78f2fbe38499c9382c059)
08e5ad2
08e5ad2
Change-Id: I96affa72412f3f38160fdca4b6efd20ca68d059f
08e5ad2
---
08e5ad2
 framework/inc/uielement/menubarmanager.hxx         |  4 +-
08e5ad2
 .../source/uielement/generictoolbarcontroller.cxx  |  2 +-
08e5ad2
 framework/source/uielement/menubarmanager.cxx      | 13 ++---
08e5ad2
 include/vcl/menu.hxx                               |  9 +---
08e5ad2
 vcl/inc/salmenu.hxx                                |  1 +
08e5ad2
 vcl/inc/unx/gtk/gtksalmenu.hxx                     |  4 +-
08e5ad2
 vcl/source/window/menu.cxx                         | 20 +++-----
08e5ad2
 vcl/unx/gtk/window/gloactiongroup.cxx              |  2 +-
08e5ad2
 vcl/unx/gtk/window/gtksalmenu.cxx                  | 59 ++++++----------------
08e5ad2
 9 files changed, 38 insertions(+), 76 deletions(-)
08e5ad2
08e5ad2
diff --git a/framework/inc/uielement/menubarmanager.hxx b/framework/inc/uielement/menubarmanager.hxx
08e5ad2
index b72d515..99f0df0 100644
08e5ad2
--- a/framework/inc/uielement/menubarmanager.hxx
08e5ad2
+++ b/framework/inc/uielement/menubarmanager.hxx
08e5ad2
@@ -95,7 +95,8 @@ class MenuBarManager : public com::sun::star::frame::XStatusListener
08e5ad2
             const OUString& aModuleIdentifier,
08e5ad2
             Menu* pMenu,
08e5ad2
             bool bDelete,
08e5ad2
-            bool bDeleteChildren );
08e5ad2
+            bool bDeleteChildren,
08e5ad2
+            bool bHasMenuBar = true );
08e5ad2
 
08e5ad2
         virtual ~MenuBarManager();
08e5ad2
 
08e5ad2
@@ -217,6 +218,7 @@ class MenuBarManager : public com::sun::star::frame::XStatusListener
08e5ad2
         bool                                                                               m_bRetrieveImages : 1,
08e5ad2
                                                                                                m_bAcceleratorCfg : 1;
08e5ad2
         bool                                                                               m_bModuleIdentified;
08e5ad2
+        bool                                                                            m_bHasMenuBar;
08e5ad2
         OUString                                                                        m_aMenuItemCommand;
08e5ad2
         OUString                                                                        m_aModuleIdentifier;
08e5ad2
         Menu*                                                                                  m_pVCLMenu;
08e5ad2
diff --git a/framework/source/uielement/generictoolbarcontroller.cxx b/framework/source/uielement/generictoolbarcontroller.cxx
08e5ad2
index 183da37..6e83c54 100644
08e5ad2
--- a/framework/source/uielement/generictoolbarcontroller.cxx
08e5ad2
+++ b/framework/source/uielement/generictoolbarcontroller.cxx
08e5ad2
@@ -348,7 +348,7 @@ MenuToolbarController::createPopupWindow() throw (::com::sun::star::uno::Runtime
08e5ad2
         Reference< XDispatchProvider > xDispatch;
08e5ad2
         Reference< XURLTransformer > xURLTransformer = URLTransformer::create( m_xContext );
08e5ad2
         pMenu = new Toolbarmenu();
08e5ad2
-        m_xMenuManager.set( new MenuBarManager( m_xContext, m_xFrame, xURLTransformer, xDispatch, m_aModuleIdentifier, pMenu, true, true ) );
08e5ad2
+        m_xMenuManager.set( new MenuBarManager( m_xContext, m_xFrame, xURLTransformer, xDispatch, m_aModuleIdentifier, pMenu, true, true, false ) );
08e5ad2
         if (m_xMenuManager.is())
08e5ad2
         {
08e5ad2
             MenuBarManager& rMgr = dynamic_cast<MenuBarManager&>(*m_xMenuManager.get());
08e5ad2
diff --git a/framework/source/uielement/menubarmanager.cxx b/framework/source/uielement/menubarmanager.cxx
08e5ad2
index 13e145f..2096408 100644
08e5ad2
--- a/framework/source/uielement/menubarmanager.cxx
08e5ad2
+++ b/framework/source/uielement/menubarmanager.cxx
08e5ad2
@@ -135,12 +135,13 @@ MenuBarManager::MenuBarManager(
08e5ad2
     const Reference< XURLTransformer >& _xURLTransformer,
08e5ad2
     const Reference< XDispatchProvider >& rDispatchProvider,
08e5ad2
     const OUString& rModuleIdentifier,
08e5ad2
-    Menu* pMenu, bool bDelete, bool bDeleteChildren ):
08e5ad2
+    Menu* pMenu, bool bDelete, bool bDeleteChildren, bool bHasMenuBar ):
08e5ad2
     OWeakObject()
08e5ad2
     , m_bDisposed( false )
08e5ad2
     , m_bRetrieveImages( false )
08e5ad2
     , m_bAcceleratorCfg( false )
08e5ad2
     , m_bModuleIdentified( false )
08e5ad2
+    , m_bHasMenuBar( bHasMenuBar )
08e5ad2
     , m_aListenerContainer( m_mutex )
08e5ad2
     , m_xContext(rxContext)
08e5ad2
     , m_xURLTransformer(_xURLTransformer)
08e5ad2
@@ -163,6 +164,7 @@ MenuBarManager::MenuBarManager(
08e5ad2
     , m_bRetrieveImages( true )
08e5ad2
     , m_bAcceleratorCfg( false )
08e5ad2
     , m_bModuleIdentified( false )
08e5ad2
+    , m_bHasMenuBar( true )
08e5ad2
     , m_aListenerContainer( m_mutex )
08e5ad2
     , m_xContext(rxContext)
08e5ad2
     , m_xURLTransformer(_xURLTransformer)
08e5ad2
@@ -392,9 +394,6 @@ throw ( RuntimeException, std::exception )
08e5ad2
 
08e5ad2
     SolarMutexGuard aSolarGuard;
08e5ad2
     {
08e5ad2
-        vcl::MenuInvalidator::Invalidated();
08e5ad2
-    }
08e5ad2
-    {
08e5ad2
         if ( m_bDisposed )
08e5ad2
             return;
08e5ad2
 
08e5ad2
@@ -492,6 +491,8 @@ throw ( RuntimeException, std::exception )
08e5ad2
                 pMenuItemHandler->xMenuItemDispatch.clear();
08e5ad2
             }
08e5ad2
         }
08e5ad2
+        if ( m_bHasMenuBar && !m_bActive )
08e5ad2
+            m_pVCLMenu->UpdateNativeMenu();
08e5ad2
     }
08e5ad2
 }
08e5ad2
 
08e5ad2
@@ -896,8 +897,8 @@ IMPL_LINK_TYPED( MenuBarManager, Activate, Menu *, pMenu, bool )
08e5ad2
                                 if ( !bPopupMenu )
08e5ad2
                                 {
08e5ad2
                                     xMenuItemDispatch->addStatusListener( static_cast< XStatusListener* >( this ), aTargetURL );
08e5ad2
-                                    xMenuItemDispatch->removeStatusListener( static_cast< XStatusListener* >( this ), aTargetURL );
08e5ad2
-                                    xMenuItemDispatch->addStatusListener( static_cast< XStatusListener* >( this ), aTargetURL );
08e5ad2
+                                    if ( !m_bHasMenuBar )
08e5ad2
+                                        xMenuItemDispatch->removeStatusListener( static_cast< XStatusListener* >( this ), aTargetURL );
08e5ad2
                                 }
08e5ad2
                             }
08e5ad2
                             else if ( !bPopupMenu )
08e5ad2
diff --git a/include/vcl/menu.hxx b/include/vcl/menu.hxx
08e5ad2
index 2a4abcf..a44f2a8 100644
08e5ad2
--- a/include/vcl/menu.hxx
08e5ad2
+++ b/include/vcl/menu.hxx
08e5ad2
@@ -308,6 +308,8 @@ public:
08e5ad2
     void RemoveDisabledEntries( bool bCheckPopups = true, bool bRemoveEmptyPopups = false );
08e5ad2
     bool HasValidEntries( bool bCheckPopups = true );
08e5ad2
 
08e5ad2
+    void UpdateNativeMenu();
08e5ad2
+
08e5ad2
     void SetItemText( sal_uInt16 nItemId, const OUString& rStr );
08e5ad2
     OUString GetItemText( sal_uInt16 nItemId ) const;
08e5ad2
 
08e5ad2
@@ -413,13 +415,6 @@ public:
08e5ad2
 };
08e5ad2
 
08e5ad2
 
08e5ad2
-namespace vcl { namespace MenuInvalidator {
08e5ad2
-
08e5ad2
-VCL_DLLPUBLIC VclEventListeners2* GetMenuInvalidateListeners();
08e5ad2
-VCL_DLLPUBLIC void Invalidated();
08e5ad2
-
08e5ad2
-}}
08e5ad2
-
08e5ad2
 class VCL_DLLPUBLIC MenuBar : public Menu
08e5ad2
 {
08e5ad2
     Link<> maCloseHdl;
08e5ad2
diff --git a/vcl/inc/salmenu.hxx b/vcl/inc/salmenu.hxx
08e5ad2
index aaea364..182958a 100644
08e5ad2
--- a/vcl/inc/salmenu.hxx
08e5ad2
+++ b/vcl/inc/salmenu.hxx
08e5ad2
@@ -80,6 +80,7 @@ public:
08e5ad2
     virtual bool ShowNativePopupMenu(FloatingWindow * pWin, const Rectangle& rRect, FloatWinPopupFlags nFlags);
08e5ad2
     virtual bool AddMenuBarButton( const SalMenuButtonItem& ); // return false if not implemented or failure
08e5ad2
     virtual void RemoveMenuBarButton( sal_uInt16 nId );
08e5ad2
+    virtual void Update() {}
08e5ad2
 
08e5ad2
     // TODO: implement show/hide for the Win/Mac VCL native backends
08e5ad2
     virtual void ShowItem( unsigned nPos, bool bShow ) { EnableItem( nPos, bShow ); }
08e5ad2
diff --git a/vcl/inc/unx/gtk/gtksalmenu.hxx b/vcl/inc/unx/gtk/gtksalmenu.hxx
08e5ad2
index e74de22..a8f289c 100644
08e5ad2
--- a/vcl/inc/unx/gtk/gtksalmenu.hxx
08e5ad2
+++ b/vcl/inc/unx/gtk/gtksalmenu.hxx
08e5ad2
@@ -97,11 +97,11 @@ public:
08e5ad2
     void                        NativeSetAccelerator( unsigned nSection, unsigned nItemPos, const vcl::KeyCode& rKeyCode, const OUString& rKeyName );
08e5ad2
 
08e5ad2
     void                        DispatchCommand( gint itemId, const gchar* aCommand );
08e5ad2
-    void                        Activate();
08e5ad2
+    void                        Activate( const gchar* aMenuCommand = nullptr );
08e5ad2
     void                        Deactivate( const gchar* aMenuCommand );
08e5ad2
     void                        Display( bool bVisible );
08e5ad2
     bool                        PrepUpdate();
08e5ad2
-    void                        Update();           // Update this menu only.
08e5ad2
+    virtual void                Update() override;  // Update this menu only.
08e5ad2
     void                        UpdateFull();       // Update full menu hierarchy from this menu.
08e5ad2
 };
08e5ad2
 
08e5ad2
diff --git a/vcl/source/window/menu.cxx b/vcl/source/window/menu.cxx
08e5ad2
index cb83637..70e5ea1 100644
08e5ad2
--- a/vcl/source/window/menu.cxx
08e5ad2
+++ b/vcl/source/window/menu.cxx
08e5ad2
@@ -2295,6 +2295,12 @@ sal_uLong Menu::DeactivateMenuBar(sal_uLong nFocusId)
08e5ad2
     return nFocusId;
08e5ad2
 }
08e5ad2
 
08e5ad2
+void Menu::UpdateNativeMenu()
08e5ad2
+{
08e5ad2
+    if ( ImplGetSalMenu() )
08e5ad2
+        ImplGetSalMenu()->Update();
08e5ad2
+}
08e5ad2
+
08e5ad2
 void Menu::MenuBarKeyInput(const KeyEvent&)
08e5ad2
 {
08e5ad2
 }
08e5ad2
@@ -3200,18 +3206,4 @@ ImplMenuDelData::~ImplMenuDelData()
08e5ad2
         const_cast< Menu* >( mpMenu )->ImplRemoveDel( *this );
08e5ad2
 }
08e5ad2
 
08e5ad2
-namespace vcl { namespace MenuInvalidator {
08e5ad2
-    static VclEventListeners2* pMenuInvalidateListeners = NULL;
08e5ad2
-    VclEventListeners2* GetMenuInvalidateListeners()
08e5ad2
-    {
08e5ad2
-        if(!pMenuInvalidateListeners)
08e5ad2
-            pMenuInvalidateListeners = new VclEventListeners2();
08e5ad2
-        return pMenuInvalidateListeners;
08e5ad2
-    }
08e5ad2
-    void Invalidated()
08e5ad2
-    {
08e5ad2
-        VclSimpleEvent aEvent(0);
08e5ad2
-        GetMenuInvalidateListeners()->callListeners(&aEvent);
08e5ad2
-    };
08e5ad2
-} }
08e5ad2
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
08e5ad2
diff --git a/vcl/unx/gtk/window/gloactiongroup.cxx b/vcl/unx/gtk/window/gloactiongroup.cxx
08e5ad2
index 23307fd..2066abd 100644
08e5ad2
--- a/vcl/unx/gtk/window/gloactiongroup.cxx
08e5ad2
+++ b/vcl/unx/gtk/window/gloactiongroup.cxx
08e5ad2
@@ -201,7 +201,7 @@ g_lo_action_group_perform_submenu_action (GLOActionGroup *group,
08e5ad2
         SAL_INFO("vcl.unity", "g_lo_action_group_perform_submenu_action on " << group << " to " << bState);
08e5ad2
 
08e5ad2
         if (bState)
08e5ad2
-            pSalMenu->Activate();
08e5ad2
+            pSalMenu->Activate (action_name);
08e5ad2
         else
08e5ad2
             pSalMenu->Deactivate (action_name);
08e5ad2
     }
08e5ad2
diff --git a/vcl/unx/gtk/window/gtksalmenu.cxx b/vcl/unx/gtk/window/gtksalmenu.cxx
08e5ad2
index 4a18999..b07b8e5 100644
08e5ad2
--- a/vcl/unx/gtk/window/gtksalmenu.cxx
08e5ad2
+++ b/vcl/unx/gtk/window/gtksalmenu.cxx
08e5ad2
@@ -371,51 +371,9 @@ void GtkSalMenu::SetSubMenu( SalMenuItem* pSalMenuItem, SalMenu* pSubMenu, unsig
08e5ad2
     pItem->mpSubMenu = pGtkSubMenu;
08e5ad2
 }
08e5ad2
 
08e5ad2
-static bool bInvalidMenus = false;
08e5ad2
-static gboolean RefreshMenusUnity(gpointer)
08e5ad2
-{
08e5ad2
-    SolarMutexGuard g;
08e5ad2
-
08e5ad2
-    SalDisplay* pSalDisplay = vcl_sal::getSalDisplay(GetGenericData());
08e5ad2
-    std::list< SalFrame* >::const_iterator pSalFrame = pSalDisplay->getFrames().begin();
08e5ad2
-    std::list< SalFrame* >::const_iterator pEndSalFrame = pSalDisplay->getFrames().end();
08e5ad2
-    for(; pSalFrame != pEndSalFrame; ++pSalFrame) {
08e5ad2
-        const GtkSalFrame* pGtkSalFrame = static_cast< const GtkSalFrame* >( *pSalFrame );
08e5ad2
-        GtkSalFrame* pFrameNonConst = const_cast<GtkSalFrame*>(pGtkSalFrame);
08e5ad2
-        GtkSalMenu* pSalMenu = static_cast<GtkSalMenu*>(pFrameNonConst->GetMenu());
08e5ad2
-        if(pSalMenu) {
08e5ad2
-            pSalMenu->Activate();
08e5ad2
-            pSalMenu->UpdateFull();
08e5ad2
-        }
08e5ad2
-    }
08e5ad2
-    bInvalidMenus = false;
08e5ad2
-    return FALSE;
08e5ad2
-}
08e5ad2
-
08e5ad2
-static long RefreshMenusUnity(void*, void*)
08e5ad2
-{
08e5ad2
-    if(!bInvalidMenus) {
08e5ad2
-        g_timeout_add(10, &RefreshMenusUnity, NULL);
08e5ad2
-        bInvalidMenus = true;
08e5ad2
-    }
08e5ad2
-    return 0;
08e5ad2
-}
08e5ad2
-
08e5ad2
-static Link<>* getRefreshLinkInstance()
08e5ad2
-{
08e5ad2
-    static Link<>* pLink = NULL;
08e5ad2
-    if(!pLink) {
08e5ad2
-        pLink = new Link<>(NULL, &RefreshMenusUnity);
08e5ad2
-    }
08e5ad2
-    return pLink;
08e5ad2
-}
08e5ad2
-
08e5ad2
 void GtkSalMenu::SetFrame( const SalFrame* pFrame )
08e5ad2
 {
08e5ad2
     SolarMutexGuard aGuard;
08e5ad2
-    {
08e5ad2
-        vcl::MenuInvalidator::GetMenuInvalidateListeners()->addListener(*getRefreshLinkInstance());
08e5ad2
-    }
08e5ad2
 
08e5ad2
     assert(mbMenuBar);
08e5ad2
     SAL_INFO("vcl.unity", "GtkSalMenu set to frame");
08e5ad2
@@ -671,6 +629,7 @@ void GtkSalMenu::DispatchCommand( gint itemId, const gchar *aCommand )
08e5ad2
 void GtkSalMenu::ActivateAllSubmenus(MenuBar* pMenuBar)
08e5ad2
 {
08e5ad2
     pMenuBar->HandleMenuActivateEvent(mpVCLMenu);
08e5ad2
+    pMenuBar->HandleMenuDeActivateEvent(mpVCLMenu);
08e5ad2
     for ( sal_uInt16 nPos = 0; nPos < maItems.size(); nPos++ )
08e5ad2
     {
08e5ad2
         GtkSalMenuItem *pSalItem = maItems[ nPos ];
08e5ad2
@@ -682,11 +641,23 @@ void GtkSalMenu::ActivateAllSubmenus(MenuBar* pMenuBar)
08e5ad2
     }
08e5ad2
 }
08e5ad2
 
08e5ad2
-void GtkSalMenu::Activate()
08e5ad2
+void GtkSalMenu::Activate( const gchar* aMenuCommand )
08e5ad2
 {
08e5ad2
     if ( !mbMenuBar )
08e5ad2
         return;
08e5ad2
-    ActivateAllSubmenus(static_cast<MenuBar*>(mpVCLMenu));
08e5ad2
+
08e5ad2
+    if ( !aMenuCommand ) {
08e5ad2
+        ActivateAllSubmenus( static_cast< MenuBar* >( mpVCLMenu ) );
08e5ad2
+        return;
08e5ad2
+    }
08e5ad2
+
08e5ad2
+    GtkSalMenu* pSalSubMenu = GetMenuForItemCommand( const_cast<gchar*>(aMenuCommand), TRUE );
08e5ad2
+
08e5ad2
+    if ( pSalSubMenu != nullptr ) {
08e5ad2
+        MenuBar* pMenuBar = static_cast< MenuBar* >( mpVCLMenu );
08e5ad2
+        pMenuBar->HandleMenuActivateEvent( pSalSubMenu->mpVCLMenu );
08e5ad2
+        pSalSubMenu->Update();
08e5ad2
+    }
08e5ad2
 }
08e5ad2
 
08e5ad2
 void GtkSalMenu::Deactivate( const gchar* aMenuCommand )
08e5ad2
-- 
08e5ad2
2.7.1
08e5ad2