[Libreoffice-commits] .: Branch 'feature/unitymenus-quantal' - 6 commits - vcl/inc vcl/source vcl/unx

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Fri Oct 5 04:14:25 PDT 2012


 vcl/inc/salmenu.hxx                   |    6 
 vcl/inc/unx/gtk/gtksalmenu.hxx        |   24 +-
 vcl/source/window/menu.cxx            |    6 
 vcl/unx/gtk/window/gloactiongroup.cxx |   15 +
 vcl/unx/gtk/window/gtkframe.cxx       |   81 ++++---
 vcl/unx/gtk/window/gtksalmenu.cxx     |  392 +++++++++++++++++++++++++---------
 6 files changed, 375 insertions(+), 149 deletions(-)

New commits:
commit eabf9c8f3737dc703c44e464b51d6b8044926ba7
Author: Antonio Fernandez <antonio.fernandez at aentos.es>
Date:   Thu Oct 4 16:48:04 2012 +0100

    Menus are now correctly built.
    
    Change-Id: I1a4f5750c37ddfc4b4949033138efbd2372f01c5

diff --git a/vcl/unx/gtk/window/gtkframe.cxx b/vcl/unx/gtk/window/gtkframe.cxx
index d3e9169..3a8a79e 100644
--- a/vcl/unx/gtk/window/gtkframe.cxx
+++ b/vcl/unx/gtk/window/gtkframe.cxx
@@ -521,36 +521,35 @@ static void ObjectDestroyedNotify( gpointer data )
     }
 }
 
-void ensure_dbus_setup(GdkWindow* gdkWindow, GtkSalFrame* pSalFrame)
+void ensure_dbus_setup( GdkWindow* gdkWindow, GtkSalFrame* pSalFrame )
 {
     if ( gdkWindow != NULL && g_object_get_data( G_OBJECT( gdkWindow ), "g-lo-menubar" ) == NULL )
     {
-        GMenuModel* pMenuModel = G_MENU_MODEL(g_lo_menu_new());
-        GActionGroup* pActionGroup = ((GActionGroup*)g_lo_action_group_new(reinterpret_cast<gpointer>(pSalFrame)));
-        XLIB_Window windowId = GDK_WINDOW_XID( gdkWindow );
-        gchar* aDBusPath = g_strdup_printf("/window/%lu", windowId);
-        gchar* aDBusWindowPath = g_strdup_printf( "/window/%lu", windowId );
-        gchar* aDBusMenubarPath = g_strdup_printf( "/window/%lu/menus/menubar", windowId );
         // Get a DBus session connection.
         if(!pSessionBus)
             pSessionBus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
         if( pSessionBus == NULL )
             return;
+
+        // Create menu model and action group attached to this frame.
+        GMenuModel* pMenuModel = G_MENU_MODEL( g_lo_menu_new() );
+        GActionGroup* pActionGroup = ( ( GActionGroup* ) g_lo_action_group_new( reinterpret_cast< gpointer >( pSalFrame ) ) );
+
+        // Generate menu paths.
+        XLIB_Window windowId = GDK_WINDOW_XID( gdkWindow );
+        gchar* aDBusPath = g_strdup_printf("/window/%lu", windowId);
+        gchar* aDBusWindowPath = g_strdup_printf( "/window/%lu", windowId );
+        gchar* aDBusMenubarPath = g_strdup_printf( "/window/%lu/menus/menubar", windowId );
+
+        // Publish the menu model and the action group.
         SAL_INFO("vcl.unity", "exporting menu model at " << pMenuModel << " for window " << windowId);
         pSalFrame->m_nMenuExportId = g_dbus_connection_export_menu_model (pSessionBus, aDBusMenubarPath, pMenuModel, NULL);
         pSalFrame->m_nActionGroupExportId = g_dbus_connection_export_action_group( pSessionBus, aDBusPath, pActionGroup, NULL);
 
         // Set window properties.
-        g_object_set_data_full(
-            G_OBJECT(gdkWindow),
-            "g-lo-menubar",
-            pMenuModel,
-            ObjectDestroyedNotify);
-        g_object_set_data_full(
-            G_OBJECT(gdkWindow),
-            "g-lo-action-group",
-            pActionGroup,
-            ObjectDestroyedNotify);
+        g_object_set_data_full( G_OBJECT(gdkWindow), "g-lo-menubar", pMenuModel, ObjectDestroyedNotify);
+        g_object_set_data_full( G_OBJECT(gdkWindow), "g-lo-action-group", pActionGroup, ObjectDestroyedNotify);
+
         gdk_x11_window_set_utf8_property ( gdkWindow, "_GTK_UNIQUE_BUS_NAME", g_dbus_connection_get_unique_name( pSessionBus ) );
         gdk_x11_window_set_utf8_property ( gdkWindow, "_GTK_APPLICATION_OBJECT_PATH", "" );
         gdk_x11_window_set_utf8_property ( gdkWindow, "_GTK_WINDOW_OBJECT_PATH", aDBusWindowPath );
@@ -562,10 +561,10 @@ void ensure_dbus_setup(GdkWindow* gdkWindow, GtkSalFrame* pSalFrame)
     }
 }
     
-void on_registrar_available (GDBusConnection * /*connection*/,
-                        const gchar     * /*name*/,
-                        const gchar     * /*name_owner*/,
-                        gpointer         user_data)
+void on_registrar_available( GDBusConnection * /*connection*/,
+                             const gchar     * /*name*/,
+                             const gchar     * /*name_owner*/,
+                             gpointer         user_data )
 {
     SolarMutexGuard aGuard;
     GtkSalFrame* pSalFrame = reinterpret_cast< GtkSalFrame* >( user_data );
@@ -604,17 +603,31 @@ void on_registrar_unavailable (GDBusConnection * /*connection*/,
 void GtkSalFrame::EnsureAppMenuWatch()
 {
     SolarMutexGuard aGuard;
-    if(m_nWatcherId)
-        g_bus_unwatch_name(m_nWatcherId);
+
+    if ( m_nWatcherId )
+        //g_bus_unwatch_name( m_nWatcherId );
+        return;
+
+
+    // Get a DBus session connection.
+    if ( pSessionBus == NULL )
+    {
+        pSessionBus = g_bus_get_sync( G_BUS_TYPE_SESSION, NULL, NULL );
+
+        if ( pSessionBus == NULL )
+            return;
+    }
+
     // Publish the menu only if AppMenu registrar is available.
-    m_nWatcherId = g_bus_watch_name(G_BUS_TYPE_SESSION,
-         "com.canonical.AppMenu.Registrar",
-         G_BUS_NAME_WATCHER_FLAGS_NONE,
-         on_registrar_available,
-         on_registrar_unavailable,
-         static_cast<GtkSalFrame*>(this),
-         NULL);
-    ensure_dbus_setup(gtk_widget_get_window(GTK_WIDGET(m_pWindow)), static_cast<GtkSalFrame*>(this));
+    m_nWatcherId = g_bus_watch_name_on_connection( pSessionBus,
+                                                   "com.canonical.AppMenu.Registrar",
+                                                   G_BUS_NAME_WATCHER_FLAGS_NONE,
+                                                   on_registrar_available,
+                                                   on_registrar_unavailable,
+                                                   static_cast<GtkSalFrame*>(this),
+                                                   NULL );
+
+    ensure_dbus_setup( gtk_widget_get_window(GTK_WIDGET(m_pWindow)), static_cast<GtkSalFrame*>(this) );
 }
 
 GtkSalFrame::~GtkSalFrame()
@@ -673,7 +686,8 @@ GtkSalFrame::~GtkSalFrame()
                     g_dbus_connection_unexport_menu_model(pSessionBus, m_nMenuExportId);
                 GLOMenu* pMenuModel = G_LO_MENU(g_object_get_data( G_OBJECT( m_pWindow ), "g-lo-menubar" ));
                 if(pMenuModel)
-                    g_lo_menu_remove(pMenuModel,0);
+                    //g_lo_menu_remove(pMenuModel,0);
+                    g_object_unref( pMenuModel );
             }
             if(m_nActionGroupExportId)
             {
@@ -681,7 +695,8 @@ GtkSalFrame::~GtkSalFrame()
                     g_dbus_connection_unexport_action_group(pSessionBus, m_nActionGroupExportId);
                 GLOActionGroup* pActionGroup = G_LO_ACTION_GROUP(g_object_get_data( G_OBJECT( m_pWindow ), "g-lo-action-group" ));
                 if(pActionGroup)
-                    g_lo_action_group_clear( pActionGroup );
+                    //g_lo_action_group_clear( pActionGroup );
+                    g_object_unref( pActionGroup );
             }
             gtk_widget_destroy( m_pWindow );
         }
diff --git a/vcl/unx/gtk/window/gtksalmenu.cxx b/vcl/unx/gtk/window/gtksalmenu.cxx
index 43f04f5..1fd2e6f 100644
--- a/vcl/unx/gtk/window/gtksalmenu.cxx
+++ b/vcl/unx/gtk/window/gtksalmenu.cxx
@@ -246,9 +246,9 @@ void GtkSalMenu::UpdateNativeMenu()
 
 //    SolarMutexGuard aGuard;
 
-    Menu* pVCLMenu = mpVCLMenu; // pMenu->GetMenu();
-    GLOMenu* pLOMenu = G_LO_MENU( mpMenuModel ); // G_LO_MENU( pMenu->GetMenuModel() );
-    GLOActionGroup* pActionGroup = G_LO_ACTION_GROUP( mpActionGroup ); // G_LO_ACTION_GROUP( pMenu->GetActionGroup() );
+    Menu* pVCLMenu = mpVCLMenu;
+    GLOMenu* pLOMenu = G_LO_MENU( mpMenuModel );
+    GLOActionGroup* pActionGroup = G_LO_ACTION_GROUP( mpActionGroup );
     GList *pOldCommandList = NULL;
     GList *pNewCommandList = NULL;
 
@@ -335,14 +335,13 @@ void GtkSalMenu::UpdateNativeMenu()
         }
 
         GtkSalMenu* pSubmenu = pSalMenuItem->mpSubMenu;
-        GLOMenu* pSubMenuModel = g_lo_menu_get_submenu_from_item_in_section( pLOMenu, nSection, nItemPos );
 
         if ( pSubmenu && pSubmenu->GetMenu() )
         {
             NativeSetItemCommand( nSection, nItemPos, nId, aNativeCommand, itemBits, FALSE, TRUE );
             pNewCommandList = g_list_append( pNewCommandList, g_strdup( aNativeCommand ) );
 
-            //GLOMenu* pSubMenuModel = g_lo_menu_get_submenu_from_item_in_section( pLOMenu, nSection, nItemPos );
+            GLOMenu* pSubMenuModel = g_lo_menu_get_submenu_from_item_in_section( pLOMenu, nSection, nItemPos );
 
             if ( pSubMenuModel == NULL )
             {
@@ -360,24 +359,16 @@ void GtkSalMenu::UpdateNativeMenu()
 
             pSubmenu->UpdateNativeMenu();
         }
-        else if (pSubMenuModel)
-        {
-            g_lo_menu_set_submenu_to_item_in_section( pLOMenu, nSection, nItemPos, NULL );
-        };
+//        else if (pSubMenuModel)
+//        {
+//            g_lo_menu_set_submenu_to_item_in_section( pLOMenu, nSection, nItemPos, NULL );
+//        };
 
         g_free( aNativeCommand );
 
         ++nItemPos;
         ++validItems;
     }
-//    while ( nItemPos < g_lo_menu_get_n_items_from_section( pLOMenu, nSection ) )
-//        g_lo_menu_remove_from_section( pLOMenu, nSection, nItemPos );
-//    ++nSection;
-//    if ( nSection < g_menu_model_get_n_items( G_MENU_MODEL( pLOMenu ) ) )
-//    {
-//        SAL_INFO("vcl.unity", "nSection " << nSection << " model sections " << g_menu_model_get_n_items( G_MENU_MODEL( pLOMenu ) ));
-//        g_lo_menu_remove(pLOMenu, nSection );
-//    }
 
     // Delete extra items in last section.
     RemoveSpareItemsFromNativeMenu( pLOMenu, &pOldCommandList, nSection, validItems );
@@ -404,11 +395,6 @@ void GtkSalMenu::DisconnectFrame()
  * GtkSalMenu
  */
 
-//void GtkSalMenu::UpdateNativeMenu()
-//{
-//    UpdateNativeSubMenu();
-//}
-
 GtkSalMenu::GtkSalMenu( sal_Bool bMenuBar ) :
     mbMenuBar( bMenuBar ),
     mpVCLMenu( NULL ),
@@ -421,9 +407,8 @@ GtkSalMenu::GtkSalMenu( sal_Bool bMenuBar ) :
 
 GtkSalMenu::~GtkSalMenu()
 {
-    if ( mbMenuBar == sal_True ) {
+    if ( mbMenuBar == sal_True )
         ((GtkSalFrame*) mpFrame)->SetMenu( NULL );
-    }
 
     maItems.clear();
 }
@@ -469,24 +454,40 @@ void GtkSalMenu::SetFrame( const SalFrame* pFrame )
     SAL_INFO("vcl.unity", "GtkSalMenu set to frame");
     mpFrame = static_cast< const GtkSalFrame* >( pFrame );
     GtkSalFrame* pFrameNonConst = const_cast<GtkSalFrame*>(mpFrame);
+
     // if we had a menu on the GtkSalMenu we have to free it as we generate a
     // full menu anyway and we might need to reuse an existing model and
     // actiongroup
-    if(mpMenuModel)
-    {
-        g_object_unref(G_OBJECT(mpMenuModel));
-        mpMenuModel = NULL;
-    }
-    if(mpActionGroup)
-    {
-        g_object_unref(G_OBJECT(mpActionGroup));
-        mpActionGroup = NULL;
-    }
+//    if(mpMenuModel)
+//    {
+//        g_object_unref(G_OBJECT(mpMenuModel));
+//        mpMenuModel = NULL;
+//    }
+
+//    if(mpActionGroup)
+//    {
+//        g_object_unref(G_OBJECT(mpActionGroup));
+//        mpActionGroup = NULL;
+//    }
     pFrameNonConst->SetMenu( this );
     mpFrame = static_cast< const GtkSalFrame* >( pFrame );
     pFrameNonConst->EnsureAppMenuWatch();
+
+    // Clean menu model and action group if needed.
+    GObject* pWindow = G_OBJECT( gtk_widget_get_window( GTK_WIDGET( pFrameNonConst->getWindow() ) ) );
+    GLOMenu* pMenuModel = G_LO_MENU( g_object_get_data( pWindow, "g-lo-menubar" ) );
+    GLOActionGroup* pActionGroup = G_LO_ACTION_GROUP( g_object_get_data( pWindow, "g-lo-action-group" ) );
+
+    if ( pMenuModel && g_menu_model_get_n_items( G_MENU_MODEL( pMenuModel ) ) > 0 )
+        g_lo_menu_remove( pMenuModel, 0 );
+
+    if ( pActionGroup )
+        g_lo_action_group_clear( pActionGroup );
+
+
     // Generate the main menu structure.
     UpdateNativeMenu();
+
 }
 
 const GtkSalFrame* GtkSalMenu::GetFrame() const
@@ -723,11 +724,11 @@ sal_Bool GtkSalMenu::IsItemVisible( unsigned nPos )
     return bVisible;
 }
 
-void GtkSalMenu::CheckItem( unsigned nPos, sal_Bool bCheck )
+void GtkSalMenu::CheckItem( unsigned, sal_Bool )
 {
 }
 
-void GtkSalMenu::EnableItem( unsigned nPos, sal_Bool bEnable )
+void GtkSalMenu::EnableItem( unsigned, sal_Bool )
 {
 }
 
@@ -738,23 +739,23 @@ void GtkSalMenu::ShowItem( unsigned nPos, sal_Bool bShow )
 }
 
 
-void GtkSalMenu::SetItemText( unsigned nPos, SalMenuItem* pSalMenuItem, const rtl::OUString& rText )
+void GtkSalMenu::SetItemText( unsigned, SalMenuItem*, const rtl::OUString& )
 {
 }
 
-void GtkSalMenu::SetItemImage( unsigned nPos, SalMenuItem* pSalMenuItem, const Image& rImage)
+void GtkSalMenu::SetItemImage( unsigned, SalMenuItem*, const Image& )
 {
 }
 
-void GtkSalMenu::SetAccelerator( unsigned nPos, SalMenuItem* pSalMenuItem, const KeyCode& rKeyCode, const rtl::OUString& rKeyName )
+void GtkSalMenu::SetAccelerator( unsigned, SalMenuItem*, const KeyCode&, const rtl::OUString& )
 {
 }
 
-void GtkSalMenu::SetItemCommand( unsigned nPos, SalMenuItem* pSalMenuItem, const rtl::OUString& aCommandStr )
+void GtkSalMenu::SetItemCommand( unsigned, SalMenuItem*, const rtl::OUString& )
 {
 }
 
-void GtkSalMenu::GetSystemMenuData( SystemMenuData* pData )
+void GtkSalMenu::GetSystemMenuData( SystemMenuData* )
 {
 }
 
commit bda9f461601c7fb200a9f638292d041ab66add8b
Author: Antonio Fernandez <antonio.fernandez at aentos.es>
Date:   Thu Sep 27 11:28:44 2012 +0100

    All special items are now correctly displayed.
    
    Change-Id: Ifce96d3e740a7ac89132dd23f9f51447e4372716

diff --git a/vcl/inc/unx/gtk/gtksalmenu.hxx b/vcl/inc/unx/gtk/gtksalmenu.hxx
index d99d73a..7dadbfc 100644
--- a/vcl/inc/unx/gtk/gtksalmenu.hxx
+++ b/vcl/inc/unx/gtk/gtksalmenu.hxx
@@ -104,6 +104,7 @@ public:
     void                        Deactivate( const gchar* aMenuCommand );
     void DisconnectFrame();
     void UpdateNativeMenu();
+//    void UpdateNativeSubMenu();
     bool PrepUpdate();
 };
 
diff --git a/vcl/source/window/menu.cxx b/vcl/source/window/menu.cxx
index bf41af8..1115111 100644
--- a/vcl/source/window/menu.cxx
+++ b/vcl/source/window/menu.cxx
@@ -3244,7 +3244,8 @@ void Menu::HighlightItem( sal_uInt16 nItemPos )
     }
 }
 
-void Menu::Freeze() {
+void Menu::Freeze(void)
+{
     SalMenu *pSalMenu = ImplGetSalMenu();
 
     if ( pSalMenu ) {
diff --git a/vcl/unx/gtk/window/gloactiongroup.cxx b/vcl/unx/gtk/window/gloactiongroup.cxx
index d083703..756779a 100644
--- a/vcl/unx/gtk/window/gloactiongroup.cxx
+++ b/vcl/unx/gtk/window/gloactiongroup.cxx
@@ -219,8 +219,15 @@ g_lo_action_group_change_state (GActionGroup *group,
                 g_lo_action_group_perform_submenu_action (lo_group, action_name, value);
             else
             {
+                gboolean is_new = FALSE;
+
+                /* If action already exists but has no state, it should be removed and added again. */
                 if (action->state_type == NULL)
+                {
+                    g_action_group_action_removed (G_ACTION_GROUP (group), action_name);
                     action->state_type = g_variant_type_copy (g_variant_get_type(value));
+                    is_new = TRUE;
+                }
 
                 if (g_variant_is_of_type (value, action->state_type) == TRUE)
                 {
@@ -229,7 +236,10 @@ g_lo_action_group_change_state (GActionGroup *group,
 
                     action->state = g_variant_ref (value);
 
-                    g_action_group_action_state_changed (group, action_name, value);
+                    if (is_new)
+                        g_action_group_action_added (G_ACTION_GROUP (group), action_name);
+                    else
+                        g_action_group_action_state_changed (group, action_name, value);
                 }
             }
         }
@@ -248,6 +258,9 @@ g_lo_action_group_activate (GActionGroup *group,
     GLOActionGroup *lo_group = G_LO_ACTION_GROUP (group);
     GtkSalFrame *pFrame = lo_group->priv->frame;
 
+    if ( parameter != NULL )
+        g_action_group_change_action_state( group, action_name, parameter );
+
     if ( pFrame != NULL )
     {
         GtkSalMenu* pSalMenu = static_cast< GtkSalMenu* >( pFrame->GetMenu() );
diff --git a/vcl/unx/gtk/window/gtksalmenu.cxx b/vcl/unx/gtk/window/gtksalmenu.cxx
index a31ab1a..43f04f5 100644
--- a/vcl/unx/gtk/window/gtksalmenu.cxx
+++ b/vcl/unx/gtk/window/gtksalmenu.cxx
@@ -136,7 +136,7 @@ static void KeyCodeToGdkKey ( const KeyCode& rKeyCode, guint* pGdkKeyCode, GdkMo
 bool GtkSalMenu::PrepUpdate()
 {
     const GtkSalFrame* pFrame = GetFrame();
-    if (!pFrame)
+    if (pFrame)
     {
         const GObject* pWindow = G_OBJECT(gtk_widget_get_window( GTK_WIDGET(pFrame->getWindow()) ));
         if(!pWindow)
@@ -150,12 +150,17 @@ bool GtkSalMenu::PrepUpdate()
         {
             mpMenuModel = G_MENU_MODEL( g_object_get_data( G_OBJECT( pWindow ), "g-lo-menubar" ) );
             mpActionGroup = G_ACTION_GROUP( g_object_get_data( G_OBJECT( pWindow ), "g-lo-action-group" ) );
-        }
-        if(!mpMenuModel || !mpActionGroup)
-            return false;
+        
+            if(!mpMenuModel || !mpActionGroup)
+                return false;
+        } 
+        
         SAL_INFO("vcl.unity", "updating menu model" << mpMenuModel);
+        
         return true;
     }
+
+    return false;
 }
 
 /*
@@ -234,16 +239,16 @@ void RemoveUnusedCommands( GLOActionGroup* pActionGroup, GList* pOldCommandList,
     }
 }
 
-static void UpdateNativeSubMenu( GtkSalMenu *pMenu )
+void GtkSalMenu::UpdateNativeMenu()
 {
-    if(!PrepUpdate())
+    if( !PrepUpdate() )
         return;
 
 //    SolarMutexGuard aGuard;
 
-    Menu* pVCLMenu = pMenu->GetMenu();
-    GLOMenu* pLOMenu = G_LO_MENU( pMenu->GetMenuModel() );
-    GLOActionGroup* pActionGroup = G_LO_ACTION_GROUP( pMenu->GetActionGroup() );
+    Menu* pVCLMenu = mpVCLMenu; // pMenu->GetMenu();
+    GLOMenu* pLOMenu = G_LO_MENU( mpMenuModel ); // G_LO_MENU( pMenu->GetMenuModel() );
+    GLOActionGroup* pActionGroup = G_LO_ACTION_GROUP( mpActionGroup ); // G_LO_ACTION_GROUP( pMenu->GetActionGroup() );
     GList *pOldCommandList = NULL;
     GList *pNewCommandList = NULL;
 
@@ -257,11 +262,11 @@ static void UpdateNativeSubMenu( GtkSalMenu *pMenu )
     sal_Int32 validItems = 0;
     sal_Int32 nItem;
 
-    for ( nItem = 0; nItem < ( sal_Int32 ) pMenu->GetItemCount(); nItem++ ) {
-        if ( pMenu->IsItemVisible( nItem ) == sal_False )
+    for ( nItem = 0; nItem < ( sal_Int32 ) GetItemCount(); nItem++ ) {
+        if ( IsItemVisible( nItem ) == sal_False )
             continue;
 
-        GtkSalMenuItem *pSalMenuItem = pMenu->GetItemAtPos( nItem );
+        GtkSalMenuItem *pSalMenuItem = GetItemAtPos( nItem );
         sal_uInt16 nId = pSalMenuItem->mnId;
 
         if ( pSalMenuItem->mnType == MENUITEM_SEPARATOR )
@@ -337,7 +342,7 @@ static void UpdateNativeSubMenu( GtkSalMenu *pMenu )
             NativeSetItemCommand( nSection, nItemPos, nId, aNativeCommand, itemBits, FALSE, TRUE );
             pNewCommandList = g_list_append( pNewCommandList, g_strdup( aNativeCommand ) );
 
-            GLOMenu* pSubMenuModel = g_lo_menu_get_submenu_from_item_in_section( pLOMenu, nSection, nItemPos );
+            //GLOMenu* pSubMenuModel = g_lo_menu_get_submenu_from_item_in_section( pLOMenu, nSection, nItemPos );
 
             if ( pSubMenuModel == NULL )
             {
@@ -347,11 +352,12 @@ static void UpdateNativeSubMenu( GtkSalMenu *pMenu )
 
             g_object_unref( pSubMenuModel );
 
+            pSubmenu->SetMenuModel( G_MENU_MODEL( pSubMenuModel ) );
+            pSubmenu->SetActionGroup( G_ACTION_GROUP( pActionGroup ) );
+
             pSubmenu->GetMenu()->Activate();
             pSubmenu->GetMenu()->Deactivate();
 
-            pSubmenu->SetMenuModel( G_MENU_MODEL( pSubMenuModel ) );
-            pSubmenu->SetActionGroup( pActionGroup );
             pSubmenu->UpdateNativeMenu();
         }
         else if (pSubMenuModel)
@@ -364,14 +370,14 @@ static void UpdateNativeSubMenu( GtkSalMenu *pMenu )
         ++nItemPos;
         ++validItems;
     }
-    while ( nItemPos < g_lo_menu_get_n_items_from_section( pLOMenu, nSection ) )
-        g_lo_menu_remove_from_section( pLOMenu, nSection, nItemPos );
-    ++nSection;
-    if ( nSection < g_menu_model_get_n_items( G_MENU_MODEL( pLOMenu ) ) )
-    {
-        SAL_INFO("vcl.unity", "nSection " << nSection << " model sections " << g_menu_model_get_n_items( G_MENU_MODEL( pLOMenu ) ));
-        g_lo_menu_remove(pLOMenu, nSection );
-    }
+//    while ( nItemPos < g_lo_menu_get_n_items_from_section( pLOMenu, nSection ) )
+//        g_lo_menu_remove_from_section( pLOMenu, nSection, nItemPos );
+//    ++nSection;
+//    if ( nSection < g_menu_model_get_n_items( G_MENU_MODEL( pLOMenu ) ) )
+//    {
+//        SAL_INFO("vcl.unity", "nSection " << nSection << " model sections " << g_menu_model_get_n_items( G_MENU_MODEL( pLOMenu ) ));
+//        g_lo_menu_remove(pLOMenu, nSection );
+//    }
 
     // Delete extra items in last section.
     RemoveSpareItemsFromNativeMenu( pLOMenu, &pOldCommandList, nSection, validItems );
@@ -392,20 +398,17 @@ void GtkSalMenu::DisconnectFrame()
         mpFrame = NULL;
     }
 }
-    
-void ObjectDestroyedNotify( gpointer data )
-{
-    if ( data ) {
-        g_object_unref( data );
-    }
-}
-
 
 
 /*
  * GtkSalMenu
  */
 
+//void GtkSalMenu::UpdateNativeMenu()
+//{
+//    UpdateNativeSubMenu();
+//}
+
 GtkSalMenu::GtkSalMenu( sal_Bool bMenuBar ) :
     mbMenuBar( bMenuBar ),
     mpVCLMenu( NULL ),
@@ -419,8 +422,6 @@ GtkSalMenu::GtkSalMenu( sal_Bool bMenuBar ) :
 GtkSalMenu::~GtkSalMenu()
 {
     if ( mbMenuBar == sal_True ) {
-//        g_source_remove_by_user_data( this );
-
         ((GtkSalFrame*) mpFrame)->SetMenu( NULL );
     }
 
@@ -499,6 +500,7 @@ const GtkSalFrame* GtkSalMenu::GetFrame() const
 void GtkSalMenu::NativeCheckItem( unsigned nSection, unsigned nItemPos, MenuItemBits bits, gboolean bCheck )
 {
     SolarMutexGuard aGuard;
+    
     if ( mpActionGroup == NULL )
         return;
 
@@ -510,9 +512,7 @@ void GtkSalMenu::NativeCheckItem( unsigned nSection, unsigned nItemPos, MenuItem
         GVariant *pCurrentState = g_action_group_get_action_state( mpActionGroup, aCommand );
 
         if ( bits & MIB_RADIOCHECK )
-        {
             pCheckValue = ( bCheck == TRUE ) ? g_variant_new_string( aCommand ) : g_variant_new_string( "" );
-        }
         else
         {
             // By default, all checked items are checkmark buttons.
@@ -523,7 +523,7 @@ void GtkSalMenu::NativeCheckItem( unsigned nSection, unsigned nItemPos, MenuItem
         if ( pCheckValue != NULL && ( pCurrentState == NULL || g_variant_equal( pCurrentState, pCheckValue ) == FALSE ) )
             g_action_group_change_action_state( mpActionGroup, aCommand, pCheckValue );
 
-        if ( pCurrentState )
+        if ( pCurrentState != NULL )
             g_variant_unref( pCurrentState );
     }
 
@@ -571,10 +571,10 @@ void GtkSalMenu::NativeSetAccelerator( unsigned nSection, unsigned nItemPos, con
 
     gchar* aAccelerator = gtk_accelerator_name( nKeyCode, nModifiers );
 
-    gchar* aCurrentAccel = g_lo_menu_get_accelerator_from_item_in_section( pMenu, nSection, nItemPos );
+    gchar* aCurrentAccel = g_lo_menu_get_accelerator_from_item_in_section( G_LO_MENU( mpMenuModel ), nSection, nItemPos );
 
     if ( aCurrentAccel == NULL && g_strcmp0( aCurrentAccel, aAccelerator ) != 0 )
-        g_lo_menu_set_accelerator_to_item_in_section ( pMenu, nSection, nItemPos, aAccelerator );
+        g_lo_menu_set_accelerator_to_item_in_section ( G_LO_MENU( mpMenuModel ), nSection, nItemPos, aAccelerator );
 
     g_free( aAccelerator );
 }
commit 1f6be4b90cbade793ad5d6adcc326523902f695e
Author: Antonio Fernandez <antonio.fernandez at aentos.es>
Date:   Tue Sep 25 15:08:57 2012 +0100

    Spare items and its actions are now removed.
    
    Change-Id: Idb46b5dec4351e16c5c49a355c7d3cde3aab0789

diff --git a/vcl/inc/unx/gtk/gtksalmenu.hxx b/vcl/inc/unx/gtk/gtksalmenu.hxx
index 1c4a326..d99d73a 100644
--- a/vcl/inc/unx/gtk/gtksalmenu.hxx
+++ b/vcl/inc/unx/gtk/gtksalmenu.hxx
@@ -24,15 +24,14 @@
 #ifndef GTKSALMENU_HXX
 #define GTKSALMENU_HXX
 
-#include <vcl/sv.h>
-#include <vcl/bitmap.hxx>
-#include <unx/gtk/gtkframe.hxx>
-#include <unx/salmenu.h>
-
+#include <vector>
 #include <gio/gio.h>
 
-#include "glomenu.h"
-#include "gloactiongroup.h"
+#include <unx/salmenu.h>
+#include <unx/gtk/gtkframe.hxx>
+#include <unx/gtk/glomenu.h>
+#include <unx/gtk/gloactiongroup.h>
+#include <vcl/sv.h>
 
 
 class MenuItemList;
diff --git a/vcl/unx/gtk/window/gtksalmenu.cxx b/vcl/unx/gtk/window/gtksalmenu.cxx
index c8ba23d..a31ab1a 100644
--- a/vcl/unx/gtk/window/gtksalmenu.cxx
+++ b/vcl/unx/gtk/window/gtksalmenu.cxx
@@ -158,13 +158,94 @@ bool GtkSalMenu::PrepUpdate()
     }
 }
 
-void GtkSalMenu::UpdateNativeMenu( )
+/*
+ * Menu updating methods
+ */
+
+void RemoveSpareItemsFromNativeMenu( GLOMenu* pMenu, GList** pOldCommandList, unsigned nSection, unsigned nValidItems )
+{
+    sal_Int32 nSectionItems = g_lo_menu_get_n_items_from_section( pMenu, nSection );
+
+    while ( nSectionItems > (sal_Int32) nValidItems )
+    {
+        gchar* aCommand = g_lo_menu_get_command_from_item_in_section( pMenu, nSection, --nSectionItems );
+
+        if ( aCommand != NULL && pOldCommandList != NULL )
+            *pOldCommandList = g_list_append( *pOldCommandList, g_strdup( aCommand ) );
+
+        g_free( aCommand );
+
+        g_lo_menu_remove_from_section( pMenu, nSection, nSectionItems );
+    }
+}
+
+void RemoveSpareSectionsFromNativeMenu( GLOMenu* pMenu, GList** pOldCommandList, unsigned nLastSection )
+{
+    if ( pMenu == NULL || pOldCommandList == NULL )
+        return;
+
+    sal_Int32 n = g_menu_model_get_n_items( G_MENU_MODEL( pMenu ) ) - 1;
+
+    for ( ; n > (sal_Int32) nLastSection; n-- )
+    {
+        RemoveSpareItemsFromNativeMenu( pMenu, pOldCommandList, n, 0 );
+        g_lo_menu_remove( pMenu, n );
+    }
+}
+
+gint CompareStr( gpointer str1, gpointer str2 )
+{
+    return g_strcmp0( (const gchar*) str1, (const gchar*) str2 );
+}
+
+void RemoveUnusedCommands( GLOActionGroup* pActionGroup, GList* pOldCommandList, GList* pNewCommandList )
+{
+    if ( pActionGroup == NULL || pOldCommandList == NULL )
+        return;
+
+    while ( pNewCommandList != NULL )
+    {
+        GList* pNewCommand = g_list_first( pNewCommandList );
+        pNewCommandList = g_list_remove_link( pNewCommandList, pNewCommand );
+
+        gpointer aCommand = g_list_nth_data( pNewCommand, 0 );
+
+        GList* pOldCommand = g_list_find_custom( pOldCommandList, aCommand, (GCompareFunc) CompareStr );
+
+        if ( pOldCommand != NULL )
+        {
+            pOldCommandList = g_list_remove_link( pOldCommandList, pOldCommand );
+            g_list_free_full( pOldCommand, g_free );
+        }
+
+        g_list_free_full( pNewCommand, g_free );
+    }
+
+    while ( pOldCommandList != NULL )
+    {
+        GList* pCommand = g_list_first( pOldCommandList );
+        pOldCommandList = g_list_remove_link( pOldCommandList, pCommand );
+
+        gchar* aCommand = (gchar*) g_list_nth_data( pCommand, 0 );
+
+        g_lo_action_group_remove( pActionGroup, aCommand );
+
+        g_list_free_full( pCommand, g_free );
+    }
+}
+
+static void UpdateNativeSubMenu( GtkSalMenu *pMenu )
 {
     if(!PrepUpdate())
         return;
-    Menu* pVCLMenu = GetMenu();
-    GLOMenu* pLOMenu = G_LO_MENU( GetMenuModel() );
-    GActionGroup* pActionGroup = GetActionGroup();
+
+//    SolarMutexGuard aGuard;
+
+    Menu* pVCLMenu = pMenu->GetMenu();
+    GLOMenu* pLOMenu = G_LO_MENU( pMenu->GetMenuModel() );
+    GLOActionGroup* pActionGroup = G_LO_ACTION_GROUP( pMenu->GetActionGroup() );
+    GList *pOldCommandList = NULL;
+    GList *pNewCommandList = NULL;
 
     sal_uInt16 nLOMenuSize = g_menu_model_get_n_items( G_MENU_MODEL( pLOMenu ) );
 
@@ -186,11 +267,7 @@ void GtkSalMenu::UpdateNativeMenu( )
         if ( pSalMenuItem->mnType == MENUITEM_SEPARATOR )
         {
             // Delete extra items from current section.
-            sal_uInt16 nSectionItems = g_lo_menu_get_n_items_from_section( pLOMenu, nSection );
-
-            while ( nSectionItems > validItems )
-                // FIXME Remove associated command if needed.
-                g_lo_menu_remove_from_section( pLOMenu, nSection, --nSectionItems );
+            RemoveSpareItemsFromNativeMenu( pLOMenu, &pOldCommandList, nSection, validItems );
 
             nSection++;
             nItemPos = 0;
@@ -221,6 +298,12 @@ void GtkSalMenu::UpdateNativeMenu( )
         gboolean bEnabled = ( itemEnabled == sal_True ) ? TRUE : FALSE;
         gchar* aNativeCommand = g_strdup( rtl::OUStringToOString( aCommand, RTL_TEXTENCODING_UTF8 ).getStr() );
 
+        // Store current item command in command list.
+        gchar *aCurrentCommand = g_lo_menu_get_command_from_item_in_section( pLOMenu, nSection, nItemPos );
+
+        if ( aCurrentCommand != NULL )
+            pOldCommandList = g_list_append( pOldCommandList, aCurrentCommand );
+
         // Force updating of native menu labels.
         NativeSetItemText( nSection, nItemPos, aText );
         NativeSetAccelerator( nSection, nItemPos, nAccelKey, nAccelKey.GetName( GetFrame()->GetWindow() ) );
@@ -242,6 +325,8 @@ void GtkSalMenu::UpdateNativeMenu( )
             NativeSetItemCommand( nSection, nItemPos, nId, aNativeCommand, itemBits, bChecked, FALSE );
             NativeCheckItem( nSection, nItemPos, itemBits, bChecked );
             NativeSetEnableItem( aNativeCommand, bEnabled );
+
+            pNewCommandList = g_list_append( pNewCommandList, g_strdup( aNativeCommand ) );
         }
 
         GtkSalMenu* pSubmenu = pSalMenuItem->mpSubMenu;
@@ -250,6 +335,10 @@ void GtkSalMenu::UpdateNativeMenu( )
         if ( pSubmenu && pSubmenu->GetMenu() )
         {
             NativeSetItemCommand( nSection, nItemPos, nId, aNativeCommand, itemBits, FALSE, TRUE );
+            pNewCommandList = g_list_append( pNewCommandList, g_strdup( aNativeCommand ) );
+
+            GLOMenu* pSubMenuModel = g_lo_menu_get_submenu_from_item_in_section( pLOMenu, nSection, nItemPos );
+
             if ( pSubMenuModel == NULL )
             {
                 pSubMenuModel = g_lo_menu_new();
@@ -285,15 +374,13 @@ void GtkSalMenu::UpdateNativeMenu( )
     }
 
     // Delete extra items in last section.
-    sal_Int32 nSectionItems = (sal_Int32) g_lo_menu_get_n_items_from_section( pLOMenu, nSection );
-
-    while ( nSectionItems > validItems )
-        g_lo_menu_remove_from_section( pLOMenu, nSection, --nSectionItems );
+    RemoveSpareItemsFromNativeMenu( pLOMenu, &pOldCommandList, nSection, validItems );
 
     // Delete extra sections.
-    for ( sal_Int32 n = nLOMenuSize - 1; n > nSection; )
-        // FIXME Remove associated command if needed.
-        g_lo_menu_remove( pLOMenu, n-- );
+    RemoveSpareSectionsFromNativeMenu( pLOMenu, &pOldCommandList, nSection );
+
+    // Delete unused commands.
+    RemoveUnusedCommands( pActionGroup, pOldCommandList, pNewCommandList );
 }
 
 void GtkSalMenu::DisconnectFrame()
@@ -607,7 +694,8 @@ void GtkSalMenu::Activate( const gchar* aMenuCommand )
     GtkSalMenu* pSalSubMenu = GetMenuForItemCommand( (gchar*) aMenuCommand, TRUE );
 
     if ( pSalSubMenu != NULL ) {
-        pSalSubMenu->mpVCLMenu->Activate();
+        MenuBar* pMenuBar = static_cast< MenuBar* >( mpVCLMenu );
+        pMenuBar->HandleMenuActivateEvent( pSalSubMenu->mpVCLMenu );
         pSalSubMenu->UpdateNativeMenu();
     }
 }
@@ -620,7 +708,8 @@ void GtkSalMenu::Deactivate( const gchar* aMenuCommand )
     GtkSalMenu* pSalSubMenu = GetMenuForItemCommand( (gchar*) aMenuCommand, TRUE );
 
     if ( pSalSubMenu != NULL ) {
-        pSalSubMenu->mpVCLMenu->Deactivate();
+        MenuBar* pMenuBar = static_cast< MenuBar* >( mpVCLMenu );
+        pMenuBar->HandleMenuDeActivateEvent( pSalSubMenu->mpVCLMenu );
     }
 }
 
commit 25d637eb322f4aa37e5048e3d46fac62fb0f40be
Author: Antonio Fernandez <antonio.fernandez at aentos.es>
Date:   Mon Sep 24 16:20:57 2012 +0100

    Extra menu items are removed when needed, but not their actions.
    
    Change-Id: If817b03cc7b30bfeb751e47fff4aa571fdaaafdc

diff --git a/vcl/unx/gtk/window/gtksalmenu.cxx b/vcl/unx/gtk/window/gtksalmenu.cxx
index acd176c..c8ba23d 100644
--- a/vcl/unx/gtk/window/gtksalmenu.cxx
+++ b/vcl/unx/gtk/window/gtksalmenu.cxx
@@ -171,12 +171,12 @@ void GtkSalMenu::UpdateNativeMenu( )
     if ( nLOMenuSize == 0 )
         g_lo_menu_new_section( pLOMenu, 0, NULL );
 
-    sal_uInt16 nSection = 0;
-    sal_uInt16 nItemPos = 0;
-    sal_uInt16 validItems = 0;
-    sal_uInt16 nItem;
+    sal_Int32 nSection = 0;
+    sal_Int32 nItemPos = 0;
+    sal_Int32 validItems = 0;
+    sal_Int32 nItem;
 
-    for ( nItem = 0; nItem < pMenu->GetItemCount(); nItem++ ) {
+    for ( nItem = 0; nItem < ( sal_Int32 ) pMenu->GetItemCount(); nItem++ ) {
         if ( pMenu->IsItemVisible( nItem ) == sal_False )
             continue;
 
@@ -185,9 +185,13 @@ void GtkSalMenu::UpdateNativeMenu( )
 
         if ( pSalMenuItem->mnType == MENUITEM_SEPARATOR )
         {
-            while ( nItemPos < g_lo_menu_get_n_items_from_section( pLOMenu, nSection ) )
-                g_lo_menu_remove_from_section( pLOMenu, nSection, nItemPos );
-            
+            // Delete extra items from current section.
+            sal_uInt16 nSectionItems = g_lo_menu_get_n_items_from_section( pLOMenu, nSection );
+
+            while ( nSectionItems > validItems )
+                // FIXME Remove associated command if needed.
+                g_lo_menu_remove_from_section( pLOMenu, nSection, --nSectionItems );
+
             nSection++;
             nItemPos = 0;
             validItems = 0;
@@ -279,6 +283,17 @@ void GtkSalMenu::UpdateNativeMenu( )
         SAL_INFO("vcl.unity", "nSection " << nSection << " model sections " << g_menu_model_get_n_items( G_MENU_MODEL( pLOMenu ) ));
         g_lo_menu_remove(pLOMenu, nSection );
     }
+
+    // Delete extra items in last section.
+    sal_Int32 nSectionItems = (sal_Int32) g_lo_menu_get_n_items_from_section( pLOMenu, nSection );
+
+    while ( nSectionItems > validItems )
+        g_lo_menu_remove_from_section( pLOMenu, nSection, --nSectionItems );
+
+    // Delete extra sections.
+    for ( sal_Int32 n = nLOMenuSize - 1; n > nSection; )
+        // FIXME Remove associated command if needed.
+        g_lo_menu_remove( pLOMenu, n-- );
 }
 
 void GtkSalMenu::DisconnectFrame()
@@ -630,7 +645,7 @@ void GtkSalMenu::EnableItem( unsigned nPos, sal_Bool bEnable )
 void GtkSalMenu::ShowItem( unsigned nPos, sal_Bool bShow )
 {
     if ( nPos < maItems.size() )
-        ( ( GtkSalMenuItem* ) maItems[ nPos ])->mbVisible = bShow;
+        ( ( GtkSalMenuItem* ) maItems[ nPos ] )->mbVisible = bShow;
 }
 
 
commit cb099858d57d153dd8f56416acccdafad1b71887
Author: Antonio Fernandez <antonio.fernandez at aentos.es>
Date:   Mon Sep 24 13:11:45 2012 +0100

    Hidden items are not shown anymore.
    
    Change-Id: I957c8c7690321be58e8daaf2fb65ebef136d95bc

diff --git a/vcl/inc/salmenu.hxx b/vcl/inc/salmenu.hxx
index 2f8d680..3411cb2 100644
--- a/vcl/inc/salmenu.hxx
+++ b/vcl/inc/salmenu.hxx
@@ -75,7 +75,7 @@ public:
     virtual ~SalMenu();
 
     virtual sal_Bool VisibleMenuBar() = 0;  // must return sal_True to actually DISPLAY native menu bars
-                            // otherwise only menu messages are processed (eg, OLE on Windows)
+                                            // otherwise only menu messages are processed (eg, OLE on Windows)
 
     virtual void InsertItem( SalMenuItem* pSalMenuItem, unsigned nPos ) = 0;
     virtual void RemoveItem( unsigned nPos ) = 0;
@@ -91,7 +91,9 @@ public:
     virtual bool AddMenuBarButton( const SalMenuButtonItem& ); // return false if not implemented or failure
     virtual void RemoveMenuBarButton( sal_uInt16 nId );
 
-    virtual void SetItemCommand( unsigned nPos, SalMenuItem* pSalMenuItem, const rtl::OUString& aCommandStr ) {}
+    // FIXME: Make the other VCL native backends to work with these new methods.
+    virtual void SetItemCommand( unsigned, SalMenuItem*, const rtl::OUString& ) {}
+    virtual void ShowItem( unsigned nPos, sal_Bool bShow ) { EnableItem( nPos, bShow ); }
     virtual void Freeze() {}
 
     // return an empty rectangle if not implemented
diff --git a/vcl/inc/unx/gtk/gtksalmenu.hxx b/vcl/inc/unx/gtk/gtksalmenu.hxx
index e9ffb01..1c4a326 100644
--- a/vcl/inc/unx/gtk/gtksalmenu.hxx
+++ b/vcl/inc/unx/gtk/gtksalmenu.hxx
@@ -69,6 +69,7 @@ public:
     virtual const GtkSalFrame*  GetFrame() const;
     virtual void                CheckItem( unsigned nPos, sal_Bool bCheck );
     virtual void                EnableItem( unsigned nPos, sal_Bool bEnable );
+    virtual void                ShowItem( unsigned nPos, sal_Bool bShow );
     virtual void                SetItemText( unsigned nPos, SalMenuItem* pSalMenuItem, const rtl::OUString& rText );
     virtual void                SetItemImage( unsigned nPos, SalMenuItem* pSalMenuItem, const Image& rImage);
     virtual void                SetAccelerator( unsigned nPos, SalMenuItem* pSalMenuItem, const KeyCode& rKeyCode, const rtl::OUString& rKeyName );
@@ -85,6 +86,7 @@ public:
     virtual GtkSalMenuItem*     GetItemAtPos( unsigned nPos ) { return maItems[ nPos ]; }
     virtual void                SetActionGroup( GActionGroup* pActionGroup ) { mpActionGroup = pActionGroup; }
     virtual GActionGroup*       GetActionGroup() { return mpActionGroup; }
+    virtual sal_Bool            IsItemVisible( unsigned nPos );
 
     void                        NativeSetItemText( unsigned nSection, unsigned nItemPos, const rtl::OUString& rText );
     void                        NativeSetItemCommand( unsigned nSection,
@@ -114,9 +116,10 @@ public:
 
     sal_uInt16          mnId;               // Item ID
     MenuItemType        mnType;             // Item type
-    Menu*               mpVCLMenu;          // VCL Menu into which this MenuItem is inserted
-    GtkSalMenu*         mpParentMenu;       // The menu in which this menu item is inserted
-    GtkSalMenu*         mpSubMenu;          // Sub menu of this item (if defined)
+    sal_Bool            mbVisible;          // Item visibility.
+    Menu*               mpVCLMenu;          // VCL Menu into which this menu item is inserted
+    GtkSalMenu*         mpParentMenu;       // The menu into which this menu item is inserted
+    GtkSalMenu*         mpSubMenu;          // Submenu of this item (if defined)
 };
 
 #endif // GTKSALMENU_HXX
diff --git a/vcl/source/window/menu.cxx b/vcl/source/window/menu.cxx
index 7fc74e4..bf41af8 100644
--- a/vcl/source/window/menu.cxx
+++ b/vcl/source/window/menu.cxx
@@ -1811,7 +1811,8 @@ void Menu::ShowItem( sal_uInt16 nItemId, sal_Bool bVisible )
         // as long as there is no support to hide native menu entries, we just disable them
         // TODO: add support to show/hide native menu entries
         if( ImplGetSalMenu() )
-            ImplGetSalMenu()->EnableItem( nPos, bVisible );
+//            ImplGetSalMenu()->EnableItem( nPos, bVisible );
+            ImplGetSalMenu()->ShowItem( nPos, bVisible );
     }
 }
 
diff --git a/vcl/unx/gtk/window/gtksalmenu.cxx b/vcl/unx/gtk/window/gtksalmenu.cxx
index bad553e..acd176c 100644
--- a/vcl/unx/gtk/window/gtksalmenu.cxx
+++ b/vcl/unx/gtk/window/gtksalmenu.cxx
@@ -31,6 +31,8 @@
 #  include <gdk/gdkkeysyms-compat.h>
 #endif
 
+#include <svtools/menuoptions.hxx>
+
 #include <framework/menuconfiguration.hxx>
 
 #include <sal/log.hxx>
@@ -136,23 +138,24 @@ bool GtkSalMenu::PrepUpdate()
     const GtkSalFrame* pFrame = GetFrame();
     if (!pFrame)
     {
-    const GObject* pWindow = G_OBJECT(gtk_widget_get_window( GTK_WIDGET(pFrame->getWindow()) ));
-    if(!pWindow)
-    {
-        SAL_INFO("vcl.unity", "not updating menu model, I have no frame " << mpMenuModel);
-        return false;
-    }
+        const GObject* pWindow = G_OBJECT(gtk_widget_get_window( GTK_WIDGET(pFrame->getWindow()) ));
+        if(!pWindow)
+        {
+            SAL_INFO("vcl.unity", "not updating menu model, I have no frame " << mpMenuModel);
+            return false;
+        }
     
-    // the root menu does not have its own model and has to use the one owned by the frame
-    if(mbMenuBar)
-    {
-        mpMenuModel = G_MENU_MODEL( g_object_get_data( G_OBJECT( pWindow ), "g-lo-menubar" ) );
-        mpActionGroup = G_ACTION_GROUP( g_object_get_data( G_OBJECT( pWindow ), "g-lo-action-group" ) );
+        // the root menu does not have its own model and has to use the one owned by the frame
+        if(mbMenuBar)
+        {
+            mpMenuModel = G_MENU_MODEL( g_object_get_data( G_OBJECT( pWindow ), "g-lo-menubar" ) );
+            mpActionGroup = G_ACTION_GROUP( g_object_get_data( G_OBJECT( pWindow ), "g-lo-action-group" ) );
+        }
+        if(!mpMenuModel || !mpActionGroup)
+            return false;
+        SAL_INFO("vcl.unity", "updating menu model" << mpMenuModel);
+        return true;
     }
-    if(!mpMenuModel || !mpActionGroup)
-        return false;
-    SAL_INFO("vcl.unity", "updating menu model" << mpMenuModel);
-    return true;
 }
 
 void GtkSalMenu::UpdateNativeMenu( )
@@ -173,16 +176,21 @@ void GtkSalMenu::UpdateNativeMenu( )
     sal_uInt16 validItems = 0;
     sal_uInt16 nItem;
 
-    for ( nItem = 0; nItem < GetItemCount(); nItem++ ) {
-        GtkSalMenuItem *pSalMenuItem = GetItemAtPos( nItem );
+    for ( nItem = 0; nItem < pMenu->GetItemCount(); nItem++ ) {
+        if ( pMenu->IsItemVisible( nItem ) == sal_False )
+            continue;
+
+        GtkSalMenuItem *pSalMenuItem = pMenu->GetItemAtPos( nItem );
         sal_uInt16 nId = pSalMenuItem->mnId;
 
         if ( pSalMenuItem->mnType == MENUITEM_SEPARATOR )
         {
             while ( nItemPos < g_lo_menu_get_n_items_from_section( pLOMenu, nSection ) )
                 g_lo_menu_remove_from_section( pLOMenu, nSection, nItemPos );
+            
             nSection++;
             nItemPos = 0;
+            validItems = 0;
 
             if ( nLOMenuSize <= nSection )
             {
@@ -601,6 +609,16 @@ void GtkSalMenu::Deactivate( const gchar* aMenuCommand )
     }
 }
 
+sal_Bool GtkSalMenu::IsItemVisible( unsigned nPos )
+{
+    sal_Bool bVisible = sal_False;
+
+    if ( nPos < maItems.size() )
+        bVisible = ( ( GtkSalMenuItem* ) maItems[ nPos ])->mbVisible;
+
+    return bVisible;
+}
+
 void GtkSalMenu::CheckItem( unsigned nPos, sal_Bool bCheck )
 {
 }
@@ -609,6 +627,13 @@ void GtkSalMenu::EnableItem( unsigned nPos, sal_Bool bEnable )
 {
 }
 
+void GtkSalMenu::ShowItem( unsigned nPos, sal_Bool bShow )
+{
+    if ( nPos < maItems.size() )
+        ( ( GtkSalMenuItem* ) maItems[ nPos ])->mbVisible = bShow;
+}
+
+
 void GtkSalMenu::SetItemText( unsigned nPos, SalMenuItem* pSalMenuItem, const rtl::OUString& rText )
 {
 }
@@ -642,6 +667,7 @@ void GtkSalMenu::Freeze()
 GtkSalMenuItem::GtkSalMenuItem( const SalItemParams* pItemData ) :
     mnId( pItemData->nId ),
     mnType( pItemData->eType ),
+    mbVisible( sal_True ),
     mpVCLMenu( pItemData->pMenu ),
     mpParentMenu( NULL ),
     mpSubMenu( NULL )
commit 82c4e77a75835049f11f46962c70f82fca5bf4c7
Author: Antonio Fernandez <antonio.fernandez at aentos.es>
Date:   Sat Sep 22 20:21:44 2012 +0100

    All accelerators should be displayed now.
    
    Change-Id: I4599e9f23ba0b1150a3a24cb5d10736895c38891

diff --git a/vcl/inc/unx/gtk/gtksalmenu.hxx b/vcl/inc/unx/gtk/gtksalmenu.hxx
index c798d41..e9ffb01 100644
--- a/vcl/inc/unx/gtk/gtksalmenu.hxx
+++ b/vcl/inc/unx/gtk/gtksalmenu.hxx
@@ -45,7 +45,6 @@ private:
     std::vector< GtkSalMenuItem* >  maItems;
 
     sal_Bool                        mbMenuBar;
-    sal_Bool                        mbVisible;
     Menu*                           mpVCLMenu;
     GtkSalMenu*                     mpParentSalMenu;
     const GtkSalFrame*              mpFrame;
diff --git a/vcl/unx/gtk/window/gtksalmenu.cxx b/vcl/unx/gtk/window/gtksalmenu.cxx
index fc568d3..bad553e 100644
--- a/vcl/unx/gtk/window/gtksalmenu.cxx
+++ b/vcl/unx/gtk/window/gtksalmenu.cxx
@@ -22,12 +22,15 @@
 
 #include <unx/gtk/gtksalmenu.hxx>
 
-//#include <gtk/gtk.h>
 #include <unx/gtk/glomenu.h>
 #include <unx/gtk/gloactiongroup.h>
 #include <vcl/menu.hxx>
 #include <unx/gtk/gtkinst.hxx>
 
+#if GTK_CHECK_VERSION(3,0,0)
+#  include <gdk/gdkkeysyms-compat.h>
+#endif
+
 #include <framework/menuconfiguration.hxx>
 
 #include <sal/log.hxx>
@@ -47,29 +50,85 @@ static gchar* GetCommandForSpecialItem( GtkSalMenuItem* pSalMenuItem )
     return aCommand;
 }
 
-// FIXME: Check for missing keys. Maybe translating keycodes would be safer...
-rtl::OUString GetGtkKeyName( rtl::OUString keyName )
+static void KeyCodeToGdkKey ( const KeyCode& rKeyCode, guint* pGdkKeyCode, GdkModifierType *pGdkModifiers )
 {
-    rtl::OUString aGtkKeyName("");
+    if ( pGdkKeyCode == NULL || pGdkModifiers == NULL )
+        return;
+
+    // Get GDK key modifiers
+    GdkModifierType nModifiers = (GdkModifierType) 0;
+
+    if ( rKeyCode.IsShift() )
+        nModifiers = (GdkModifierType) ( nModifiers | GDK_SHIFT_MASK );
+
+    if ( rKeyCode.IsMod1() )
+        nModifiers = (GdkModifierType) ( nModifiers | GDK_CONTROL_MASK );
 
-    sal_Int32 nIndex = 0;
+    if ( rKeyCode.IsMod2() )
+        nModifiers = (GdkModifierType) ( nModifiers | GDK_MOD1_MASK );
 
-    do
+    *pGdkModifiers = nModifiers;
+
+    // Get GDK keycode.
+    guint nKeyCode = 0;
+
+    guint nCode = rKeyCode.GetCode();
+
+    if ( nCode >= KEY_0 && nCode <= KEY_9 )
+        nKeyCode = ( nCode - KEY_0 ) + GDK_0;
+    else if ( nCode >= KEY_A && nCode <= KEY_Z )
+        nKeyCode = ( nCode - KEY_A ) + GDK_A;
+    else if ( nCode >= KEY_F1 && nCode <= KEY_F26 )
+        nKeyCode = ( nCode - KEY_F1 ) + GDK_F1;
+    else
     {
-        rtl::OUString token = keyName.getToken( 0, '+', nIndex );
-
-        if ( token == "Ctrl" ) {
-            aGtkKeyName += "<Control>";
-        } else if ( token == "Alt" ) {
-            aGtkKeyName += "<Alt>";
-        } else if ( token == "Shift" ) {
-            aGtkKeyName += "<Shift>";
-        } else {
-            aGtkKeyName += token;
+        switch( nCode )
+        {
+        case KEY_DOWN:          nKeyCode = GDK_Down;            break;
+        case KEY_UP:            nKeyCode = GDK_Up;              break;
+        case KEY_LEFT:          nKeyCode = GDK_Left;            break;
+        case KEY_RIGHT:         nKeyCode = GDK_Right;           break;
+        case KEY_HOME:          nKeyCode = GDK_Home;            break;
+        case KEY_END:           nKeyCode = GDK_End;             break;
+        case KEY_PAGEUP:        nKeyCode = GDK_Page_Up;         break;
+        case KEY_PAGEDOWN:      nKeyCode = GDK_Page_Down;       break;
+        case KEY_RETURN:        nKeyCode = GDK_Return;          break;
+        case KEY_ESCAPE:        nKeyCode = GDK_Escape;          break;
+        case KEY_TAB:           nKeyCode = GDK_Tab;             break;
+        case KEY_BACKSPACE:     nKeyCode = GDK_BackSpace;       break;
+        case KEY_SPACE:         nKeyCode = GDK_space;           break;
+        case KEY_INSERT:        nKeyCode = GDK_Insert;          break;
+        case KEY_DELETE:        nKeyCode = GDK_Delete;          break;
+        case KEY_ADD:           nKeyCode = GDK_plus;            break;
+        case KEY_SUBTRACT:      nKeyCode = GDK_minus;           break;
+        case KEY_MULTIPLY:      nKeyCode = GDK_asterisk;        break;
+        case KEY_DIVIDE:        nKeyCode = GDK_slash;           break;
+        case KEY_POINT:         nKeyCode = GDK_period;          break;
+        case KEY_COMMA:         nKeyCode = GDK_comma;           break;
+        case KEY_LESS:          nKeyCode = GDK_less;            break;
+        case KEY_GREATER:       nKeyCode = GDK_greater;         break;
+        case KEY_EQUAL:         nKeyCode = GDK_equal;           break;
+        case KEY_FIND:          nKeyCode = GDK_Find;            break;
+        case KEY_CONTEXTMENU:   nKeyCode = GDK_Menu;            break;
+        case KEY_HELP:          nKeyCode = GDK_Help;            break;
+        case KEY_UNDO:          nKeyCode = GDK_Undo;            break;
+        case KEY_REPEAT:        nKeyCode = GDK_Redo;            break;
+        case KEY_DECIMAL:       nKeyCode = GDK_KP_Decimal;      break;
+        case KEY_TILDE:         nKeyCode = GDK_asciitilde;      break;
+        case KEY_QUOTELEFT:     nKeyCode = GDK_quoteleft;       break;
+        case KEY_BRACKETLEFT:   nKeyCode = GDK_bracketleft;     break;
+        case KEY_BRACKETRIGHT:  nKeyCode = GDK_bracketright;    break;
+        case KEY_SEMICOLON:     nKeyCode = GDK_semicolon;       break;
+
+        // Special cases
+        case KEY_COPY:          nKeyCode = GDK_Copy;            break;
+        case KEY_CUT:           nKeyCode = GDK_Cut;             break;
+        case KEY_PASTE:         nKeyCode = GDK_Paste;           break;
+        case KEY_OPEN:          nKeyCode = GDK_Open;            break;
         }
-    } while ( nIndex >= 0 );
+    }
 
-    return aGtkKeyName;
+    *pGdkKeyCode = nKeyCode;
 }
 
 bool GtkSalMenu::PrepUpdate()
@@ -77,15 +136,13 @@ bool GtkSalMenu::PrepUpdate()
     const GtkSalFrame* pFrame = GetFrame();
     if (!pFrame)
     {
-        SAL_INFO("vcl.unity", "not updating menu model, I have no frame " << mpMenuModel);
-        return false;
-    }
     const GObject* pWindow = G_OBJECT(gtk_widget_get_window( GTK_WIDGET(pFrame->getWindow()) ));
     if(!pWindow)
     {
         SAL_INFO("vcl.unity", "not updating menu model, I have no frame " << mpMenuModel);
         return false;
     }
+    
     // the root menu does not have its own model and has to use the one owned by the frame
     if(mbMenuBar)
     {
@@ -241,7 +298,6 @@ void ObjectDestroyedNotify( gpointer data )
 
 GtkSalMenu::GtkSalMenu( sal_Bool bMenuBar ) :
     mbMenuBar( bMenuBar ),
-    mbVisible( sal_False ),
     mpVCLMenu( NULL ),
     mpParentSalMenu( NULL ),
     mpFrame( NULL ),
@@ -394,18 +450,23 @@ void GtkSalMenu::NativeSetItemText( unsigned nSection, unsigned nItemPos, const
 void GtkSalMenu::NativeSetAccelerator( unsigned nSection, unsigned nItemPos, const KeyCode& rKeyCode, const rtl::OUString& rKeyName )
 {
     SolarMutexGuard aGuard;
+
     if ( rKeyName.isEmpty() )
         return;
 
-    rtl::OString aAccelerator = rtl::OUStringToOString( GetGtkKeyName( rKeyName ), RTL_TEXTENCODING_UTF8 );
+    guint nKeyCode;
+    GdkModifierType nModifiers;
+
+    KeyCodeToGdkKey( rKeyCode, &nKeyCode, &nModifiers );
+
+    gchar* aAccelerator = gtk_accelerator_name( nKeyCode, nModifiers );
 
-    gchar* aCurrentAccel = g_lo_menu_get_accelerator_from_item_in_section( G_LO_MENU( mpMenuModel ), nSection, nItemPos );
+    gchar* aCurrentAccel = g_lo_menu_get_accelerator_from_item_in_section( pMenu, nSection, nItemPos );
 
-    if ( aCurrentAccel == NULL && g_strcmp0( aCurrentAccel, aAccelerator.getStr() ) != 0 )
-        g_lo_menu_set_accelerator_to_item_in_section ( G_LO_MENU( mpMenuModel ), nSection, nItemPos, aAccelerator.getStr() );
+    if ( aCurrentAccel == NULL && g_strcmp0( aCurrentAccel, aAccelerator ) != 0 )
+        g_lo_menu_set_accelerator_to_item_in_section ( pMenu, nSection, nItemPos, aAccelerator );
 
-    if ( aCurrentAccel )
-        g_free( aCurrentAccel );
+    g_free( aAccelerator );
 }
 
 void GtkSalMenu::NativeSetItemCommand( unsigned nSection,


More information about the Libreoffice-commits mailing list