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

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Fri Sep 21 05:19:30 PDT 2012


 vcl/inc/salmenu.hxx                   |    2 
 vcl/inc/unx/gtk/gtkframe.hxx          |  161 +++----
 vcl/inc/unx/gtk/gtksalmenu.hxx        |   12 
 vcl/unx/gtk/window/gloactiongroup.cxx |    2 
 vcl/unx/gtk/window/gtkframe.cxx       |    9 
 vcl/unx/gtk/window/gtksalmenu.cxx     |  763 +++++++++++++++++-----------------
 6 files changed, 481 insertions(+), 468 deletions(-)

New commits:
commit a1036bd48b3d03798b300e879ec822ef7554fffa
Author: Antonio Fernandez <antonio.fernandez at aentos.es>
Date:   Fri Sep 21 13:09:14 2012 +0100

    Total rework of how native menu is filled, but not finished yet.
    
    Change-Id: Ib59002d08f9debe2155bcf35c7069ac55f0e2106

diff --git a/vcl/inc/salmenu.hxx b/vcl/inc/salmenu.hxx
index 2f8d680..e09b7ce 100644
--- a/vcl/inc/salmenu.hxx
+++ b/vcl/inc/salmenu.hxx
@@ -91,7 +91,7 @@ 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 ) {}
+    virtual void SetItemCommand( unsigned, SalMenuItem*, const rtl::OUString& ) {}
     virtual void Freeze() {}
 
     // return an empty rectangle if not implemented
diff --git a/vcl/inc/unx/gtk/gtkframe.hxx b/vcl/inc/unx/gtk/gtkframe.hxx
index cd080d0..5c69476 100644
--- a/vcl/inc/unx/gtk/gtkframe.hxx
+++ b/vcl/inc/unx/gtk/gtkframe.hxx
@@ -246,20 +246,20 @@ class GtkSalFrame : public SalFrame
     static gboolean     signalVisibility( GtkWidget*, GdkEventVisibility*, gpointer );
     static void         signalDestroy( GtkWidget*, gpointer );
 
-    void            Center();
-    void            SetDefaultSize();
-    void            setAutoLock( bool bLock );
-    void            setScreenSaverTimeout( int nTimeout );
-
-    void            doKeyCallback( guint state,
-                                   guint keyval,
-                                   guint16 hardware_keycode,
-                                   guint8 group,
-                                   guint32 time,
-                                   sal_Unicode aOrigCode,
-                                   bool bDown,
-                                   bool bSendRelease
-                                   );
+    void                Center();
+    void                SetDefaultSize();
+    void                setAutoLock( bool bLock );
+    void                setScreenSaverTimeout( int nTimeout );
+
+    void                doKeyCallback( guint state,
+                                       guint keyval,
+                                       guint16 hardware_keycode,
+                                       guint8 group,
+                                       guint32 time,
+                                       sal_Unicode aOrigCode,
+                                       bool bDown,
+                                       bool bSendRelease
+                                     );
 
 
     GdkNativeWindow findTopLevelSystemWindow( GdkNativeWindow aWindow );
@@ -310,120 +310,127 @@ public:
     // dispatches an event, returns true if dispatched
     // and false else; if true was returned the event should
     // be swallowed
-    bool Dispatch( const XEvent* pEvent );
-    void grabPointer( sal_Bool bGrab, sal_Bool bOwnerEvents = sal_False );
-
-    GtkSalDisplay*  getDisplay();
-    GdkDisplay*     getGdkDisplay();
-    GtkWidget*  getWindow() const { return m_pWindow; }
-    GtkFixed*   getFixedContainer() const { return m_pFixedContainer; }
-    GdkWindow*  getForeignParent() const { return m_pForeignParent; }
-    GdkNativeWindow getForeignParentWindow() const { return m_aForeignParentWindow; }
-    GdkWindow*  getForeignTopLevel() const { return m_pForeignTopLevel; }
-    GdkNativeWindow getForeignTopLevelWindow() const { return m_aForeignTopLevelWindow; }
-    GdkVisibilityState getVisibilityState() const
-    { return m_nVisibility; }
-    Pixmap getBackgroundPixmap() const { return m_hBackgroundPixmap; }
-    SalX11Screen getXScreenNumber() const { return m_nXScreen; }
-    int          GetDisplayScreen() const { return maGeometry.nDisplayScreenNumber; }
+    bool                            Dispatch( const XEvent* pEvent );
+    void                            grabPointer( sal_Bool bGrab, sal_Bool bOwnerEvents = sal_False );
+
+    GtkSalDisplay*                  getDisplay();
+    GdkDisplay*                     getGdkDisplay();
+    GtkWidget*                      getWindow() const { return m_pWindow; }
+    GtkFixed*                       getFixedContainer() const { return m_pFixedContainer; }
+    GdkWindow*                      getForeignParent() const { return m_pForeignParent; }
+    GdkNativeWindow                 getForeignParentWindow() const { return m_aForeignParentWindow; }
+    GdkWindow*                      getForeignTopLevel() const { return m_pForeignTopLevel; }
+    GdkNativeWindow                 getForeignTopLevelWindow() const { return m_aForeignTopLevelWindow; }
+    GdkVisibilityState              getVisibilityState() const { return m_nVisibility; }
+    Pixmap                          getBackgroundPixmap() const { return m_hBackgroundPixmap; }
+    SalX11Screen                    getXScreenNumber() const { return m_nXScreen; }
+    int                             GetDisplayScreen() const { return maGeometry.nDisplayScreenNumber; }
     void updateScreenNumber();
 
 #if GTK_CHECK_VERSION(3,0,0)
     // only for gtk3 ...
-    void pushIgnoreDamage();
-    void popIgnoreDamage();
-    void renderArea( cairo_t *cr, cairo_rectangle_t *src );
+    void                            pushIgnoreDamage();
+    void                            popIgnoreDamage();
+    void                            renderArea( cairo_t *cr, cairo_rectangle_t *src );
 #endif
     virtual ~GtkSalFrame();
 
     // SalGraphics or NULL, but two Graphics for all SalFrames
     // must be returned
-    virtual SalGraphics*        GetGraphics();
-    virtual void                ReleaseGraphics( SalGraphics* pGraphics );
+    virtual SalGraphics*            GetGraphics();
+    virtual void                    ReleaseGraphics( SalGraphics* pGraphics );
 
     // Event must be destroyed, when Frame is destroyed
     // When Event is called, SalInstance::Yield() must be returned
     virtual sal_Bool                PostEvent( void* pData );
 
-    virtual void                SetTitle( const rtl::OUString& rTitle );
-    virtual void                SetIcon( sal_uInt16 nIcon );
-    virtual void                SetMenu( SalMenu *pSalMenu );
-    virtual SalMenu*            GetMenu( void );
-    virtual void                DrawMenuBar();
-    void                        SetWatcherId( sal_uInt32 watcherId );
-
-    virtual void                SetExtendedFrameStyle( SalExtStyle nExtStyle );
+    virtual void                    SetTitle( const rtl::OUString& rTitle );
+    virtual void                    SetIcon( sal_uInt16 nIcon );
+    virtual void                    SetMenu( SalMenu *pSalMenu );
+    virtual SalMenu*                GetMenu( void );
+    virtual void                    DrawMenuBar();
+    void                            SetWatcherId( sal_uInt32 watcherId );
+
+    unsigned                        m_nMenuModelExportId;
+    unsigned                        m_nActionGroupExportId;
+    GDBusConnection*                m_pDBusConnection;
+    void                            SetMenuModelExportId( unsigned nExportId ) { m_nMenuModelExportId = nExportId; }
+    sal_uInt32                      GetMenuModelExportId( void ) const { return m_nMenuModelExportId; }
+    void                            SetActionGroupExportId( unsigned nExportId ) { m_nActionGroupExportId = nExportId; }
+    sal_uInt32                      GetActionGroupExportId( void ) const { return m_nActionGroupExportId; }
+
+    virtual void                    SetExtendedFrameStyle( SalExtStyle nExtStyle );
     // Before the window is visible, a resize event
     // must be sent with the correct size
-    virtual void                Show( sal_Bool bVisible, sal_Bool bNoActivate = sal_False );
-    virtual void                Enable( sal_Bool bEnable );
+    virtual void                    Show( sal_Bool bVisible, sal_Bool bNoActivate = sal_False );
+    virtual void                    Enable( sal_Bool bEnable );
     // Set ClientSize and Center the Window to the desktop
     // and send/post a resize message
-    virtual void                SetMinClientSize( long nWidth, long nHeight );
-    virtual void                SetMaxClientSize( long nWidth, long nHeight );
-    virtual void                SetPosSize( long nX, long nY, long nWidth, long nHeight, sal_uInt16 nFlags );
-    virtual void                GetClientSize( long& rWidth, long& rHeight );
-    virtual void                GetWorkArea( Rectangle& rRect );
-    virtual SalFrame*           GetParent() const;
-    virtual void                SetWindowState( const SalFrameState* pState );
-    virtual sal_Bool            GetWindowState( SalFrameState* pState );
-    virtual void                ShowFullScreen( sal_Bool bFullScreen, sal_Int32 nDisplay );
+    virtual void                    SetMinClientSize( long nWidth, long nHeight );
+    virtual void                    SetMaxClientSize( long nWidth, long nHeight );
+    virtual void                    SetPosSize( long nX, long nY, long nWidth, long nHeight, sal_uInt16 nFlags );
+    virtual void                    GetClientSize( long& rWidth, long& rHeight );
+    virtual void                    GetWorkArea( Rectangle& rRect );
+    virtual SalFrame*               GetParent() const;
+    virtual void                    SetWindowState( const SalFrameState* pState );
+    virtual sal_Bool                GetWindowState( SalFrameState* pState );
+    virtual void                    ShowFullScreen( sal_Bool bFullScreen, sal_Int32 nDisplay );
     // Enable/Disable ScreenSaver, SystemAgents, ...
-    virtual void                StartPresentation( sal_Bool bStart );
+    virtual void                    StartPresentation( sal_Bool bStart );
     // Show Window over all other Windows
-    virtual void                SetAlwaysOnTop( sal_Bool bOnTop );
+    virtual void                    SetAlwaysOnTop( sal_Bool bOnTop );
 
     // Window to top and grab focus
-    virtual void                ToTop( sal_uInt16 nFlags );
+    virtual void                    ToTop( sal_uInt16 nFlags );
 
     // this function can call with the same
     // pointer style
-    virtual void                SetPointer( PointerStyle ePointerStyle );
-    virtual void                CaptureMouse( sal_Bool bMouse );
-    virtual void                SetPointerPos( long nX, long nY );
+    virtual void                    SetPointer( PointerStyle ePointerStyle );
+    virtual void                    CaptureMouse( sal_Bool bMouse );
+    virtual void                    SetPointerPos( long nX, long nY );
 
     // flush output buffer
     using SalFrame::Flush;
-    virtual void                Flush();
+    virtual void                    Flush();
     // flush output buffer, wait till outstanding operations are done
-    virtual void                Sync();
+    virtual void                    Sync();
 
-    virtual void                SetInputContext( SalInputContext* pContext );
-    virtual void                EndExtTextInput( sal_uInt16 nFlags );
+    virtual void                    SetInputContext( SalInputContext* pContext );
+    virtual void                    EndExtTextInput( sal_uInt16 nFlags );
 
-    virtual rtl::OUString              GetKeyName( sal_uInt16 nKeyCode );
-    virtual sal_Bool            MapUnicodeToKeyCode( sal_Unicode aUnicode, LanguageType aLangType, KeyCode& rKeyCode );
+    virtual rtl::OUString           GetKeyName( sal_uInt16 nKeyCode );
+    virtual sal_Bool                MapUnicodeToKeyCode( sal_Unicode aUnicode, LanguageType aLangType, KeyCode& rKeyCode );
 
     // returns the input language used for the last key stroke
     // may be LANGUAGE_DONTKNOW if not supported by the OS
-    virtual LanguageType        GetInputLanguage();
+    virtual LanguageType            GetInputLanguage();
 
-    virtual void                UpdateSettings( AllSettings& rSettings );
+    virtual void                    UpdateSettings( AllSettings& rSettings );
 
-    virtual void                Beep( SoundType eSoundType );
+    virtual void                    Beep( SoundType eSoundType );
 
     // returns system data (most prominent: window handle)
     virtual const SystemEnvData*    GetSystemData() const;
 
 
     // get current modifier and button mask
-    virtual SalPointerState     GetPointerState();
+    virtual SalPointerState         GetPointerState();
 
-    virtual SalIndicatorState   GetIndicatorState();
+    virtual SalIndicatorState       GetIndicatorState();
 
-    virtual void                SimulateKeyPress( sal_uInt16 nKeyCode );
+    virtual void                    SimulateKeyPress( sal_uInt16 nKeyCode );
 
     // set new parent window
-    virtual void                SetParent( SalFrame* pNewParent );
+    virtual void                    SetParent( SalFrame* pNewParent );
     // reparent window to act as a plugin; implementation
     // may choose to use a new system window internally
     // return false to indicate failure
-    virtual bool                SetPluginParent( SystemParentData* pNewParent );
+    virtual bool                    SetPluginParent( SystemParentData* pNewParent );
 
-    virtual void                SetBackgroundBitmap( SalBitmap* );
+    virtual void                    SetBackgroundBitmap( SalBitmap* );
 
-    virtual void                SetScreenNumber( unsigned int );
-    virtual void                SetApplicationID( const rtl::OUString &rWMClass );
+    virtual void                    SetScreenNumber( unsigned int );
+    virtual void                    SetApplicationID( const rtl::OUString &rWMClass );
 
     // shaped system windows
     // set clip region to none (-> rectangular windows, normal state)
diff --git a/vcl/inc/unx/gtk/gtksalmenu.hxx b/vcl/inc/unx/gtk/gtksalmenu.hxx
index 56aed28..af02817 100644
--- a/vcl/inc/unx/gtk/gtksalmenu.hxx
+++ b/vcl/inc/unx/gtk/gtksalmenu.hxx
@@ -88,18 +88,6 @@ public:
     virtual void                SetActionGroup( GActionGroup* pActionGroup ) { mpActionGroup = pActionGroup; }
     virtual GActionGroup*       GetActionGroup() { return mpActionGroup; }
 
-    void                        NativeSetItemText( unsigned nSection, unsigned nItemPos, const rtl::OUString& rText );
-    void                        NativeSetItemCommand( unsigned nSection,
-                                                      unsigned nItemPos,
-                                                      sal_uInt16 nId,
-                                                      const gchar* aCommand,
-                                                      MenuItemBits nBits,
-                                                      gboolean bChecked,
-                                                      gboolean bIsSubmenu );
-    void                        NativeSetEnableItem( gchar* aCommand, gboolean bEnable );
-    void                        NativeCheckItem( unsigned nSection, unsigned nItemPos, MenuItemBits bits, gboolean bCheck );
-    void                        NativeSetAccelerator( unsigned nSection, unsigned nItemPos, const KeyCode& rKeyCode, const rtl::OUString& rKeyName );
-
     void                        DispatchCommand( gint itemId, const gchar* aCommand );
     void                        Activate( const gchar* aMenuCommand );
     void                        Deactivate( const gchar* aMenuCommand );
diff --git a/vcl/unx/gtk/window/gloactiongroup.cxx b/vcl/unx/gtk/window/gloactiongroup.cxx
index d083703..37a2278 100644
--- a/vcl/unx/gtk/window/gloactiongroup.cxx
+++ b/vcl/unx/gtk/window/gloactiongroup.cxx
@@ -241,7 +241,7 @@ g_lo_action_group_change_state (GActionGroup *group,
 static void
 g_lo_action_group_activate (GActionGroup *group,
                             const gchar  *action_name,
-                            GVariant     *parameter)
+                            GVariant     */*parameter */)
 {
     GTK_YIELD_GRAB();
 
diff --git a/vcl/unx/gtk/window/gtkframe.cxx b/vcl/unx/gtk/window/gtkframe.cxx
index d43371c..6c39412 100644
--- a/vcl/unx/gtk/window/gtkframe.cxx
+++ b/vcl/unx/gtk/window/gtkframe.cxx
@@ -535,6 +535,12 @@ GtkSalFrame::~GtkSalFrame()
 
     if ( m_nWatcherId > 0 )
         g_bus_unwatch_name( m_nWatcherId );
+
+    if ( m_pDBusConnection && m_nMenuModelExportId > 0 )
+        g_dbus_connection_unexport_menu_model( m_pDBusConnection, m_nMenuModelExportId );
+
+    if ( m_pDBusConnection && m_nActionGroupExportId > 0 )
+        g_dbus_connection_unexport_action_group( m_pDBusConnection, m_nActionGroupExportId );
 }
 
 void GtkSalFrame::moveWindow( long nX, long nY )
@@ -644,6 +650,9 @@ void GtkSalFrame::InitCommon()
     m_bSetFocusOnMap    = false;
     m_pSalMenu          = NULL;
     m_nWatcherId        = 0;
+    m_nMenuModelExportId = 0;
+    m_nActionGroupExportId = 0;
+    m_pDBusConnection = NULL;
 
     gtk_widget_set_app_paintable( m_pWindow, TRUE );
     gtk_widget_set_double_buffered( m_pWindow, FALSE );
diff --git a/vcl/unx/gtk/window/gtksalmenu.cxx b/vcl/unx/gtk/window/gtksalmenu.cxx
index 60942a5..2273b2a 100644
--- a/vcl/unx/gtk/window/gtksalmenu.cxx
+++ b/vcl/unx/gtk/window/gtksalmenu.cxx
@@ -34,6 +34,7 @@
 
 using namespace std;
 
+static sal_Bool bDBusIsAvailable = sal_False;
 
 static gchar* GetCommandForSpecialItem( GtkSalMenuItem* pSalMenuItem )
 {
@@ -50,117 +51,364 @@ static gchar* GetCommandForSpecialItem( GtkSalMenuItem* pSalMenuItem )
     return aCommand;
 }
 
-static void UpdateNativeMenu2( GtkSalMenu *pMenu )
+void ObjectDestroyedNotify( gpointer data )
 {
-    if ( pMenu == NULL )
-        return;
+    if ( data ) {
+        g_object_unref( data );
+    }
+}
 
-    Menu* pVCLMenu = pMenu->GetMenu();
-    GLOMenu* pLOMenu = G_LO_MENU( pMenu->GetMenuModel() );
-    GActionGroup* pActionGroup = pMenu->GetActionGroup();
+void
+gdk_x11_window_set_utf8_property  (GdkWindow *window,
+                                   const gchar *name,
+                                   const gchar *value)
+{
+  GdkDisplay *display;
 
-    sal_uInt16 nLOMenuSize = g_menu_model_get_n_items( G_MENU_MODEL( pLOMenu ) );
+  //if (!WINDOW_IS_TOPLEVEL (window))
+    //return;
 
-    if ( nLOMenuSize == 0 )
-        g_lo_menu_new_section( pLOMenu, 0, NULL );
+  display = gdk_window_get_display (window);
 
-    sal_uInt16 nSection = 0;
-    sal_uInt16 nItemPos = 0;
-    sal_uInt16 validItems = 0;
-    sal_uInt16 nItem;
+  if (value != NULL)
+    {
+      XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
+                       GDK_WINDOW_XID (window),
+                       gdk_x11_get_xatom_by_name_for_display (display, name),
+                       gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
+                       PropModeReplace, (guchar *)value, strlen (value));
+    }
+  else
+    {
+      XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
+                       GDK_WINDOW_XID (window),
+                       gdk_x11_get_xatom_by_name_for_display (display, name));
+    }
+}
 
-    for ( nItem = 0; nItem < pMenu->GetItemCount(); nItem++ ) {
-        GtkSalMenuItem *pSalMenuItem = pMenu->GetItemAtPos( nItem );
-        sal_uInt16 nId = pSalMenuItem->mnId;
+// FIXME: Check for missing keys. Maybe translating keycodes would be safer...
+rtl::OUString GetGtkKeyName( rtl::OUString keyName )
+{
+    rtl::OUString aGtkKeyName("");
 
-        if ( pSalMenuItem->mnType == MENUITEM_SEPARATOR )
-        {
-            nSection++;
-            nItemPos = 0;
+    sal_Int32 nIndex = 0;
 
-            if ( nLOMenuSize <= nSection )
-            {
-                g_lo_menu_new_section( pLOMenu, nSection, NULL );
-                nLOMenuSize++;
-            }
+    do
+    {
+        rtl::OUString token = keyName.getToken( 0, '+', nIndex );
 
-            continue;
+        if ( token == "Ctrl" ) {
+            aGtkKeyName += "<Control>";
+        } else if ( token == "Alt" ) {
+            aGtkKeyName += "<Alt>";
+        } else if ( token == "Shift" ) {
+            aGtkKeyName += "<Shift>";
+        } else {
+            aGtkKeyName += token;
         }
+    } while ( nIndex >= 0 );
 
-        if ( nItemPos >= g_lo_menu_get_n_items_from_section( pLOMenu, nSection ) )
-            g_lo_menu_insert_in_section( pLOMenu, nSection, nItemPos, "EMPTY STRING" );
+    return aGtkKeyName;
+}
 
-        // Get internal menu item values.
-        String aText = pVCLMenu->GetItemText( nId );
-        rtl::OUString aCommand( pVCLMenu->GetItemCommand( nId ) );
-        sal_Bool itemEnabled = pVCLMenu->IsItemEnabled( nId );
-        KeyCode nAccelKey = pVCLMenu->GetAccelKey( nId );
-        sal_Bool itemChecked = pVCLMenu->IsItemChecked( nId );
-        MenuItemBits itemBits = pVCLMenu->GetItemBits( nId );
+// AppMenu watch functions.
 
-        // Convert internal values to native values.
-        gboolean bChecked = ( itemChecked == sal_True ) ? TRUE : FALSE;
-        gboolean bEnabled = ( itemEnabled == sal_True ) ? TRUE : FALSE;
-        gchar* aNativeCommand = g_strdup( rtl::OUStringToOString( aCommand, RTL_TEXTENCODING_UTF8 ).getStr() );
+static gboolean PublishMenu( gpointer user_data )
+{
+    GdkWindow* gdkWindow = GDK_WINDOW( user_data );
 
-        // Force updating of native menu labels.
-        pMenu->NativeSetItemText( nSection, nItemPos, aText );
-        pMenu->NativeSetAccelerator( nSection, nItemPos, nAccelKey, nAccelKey.GetName( pMenu->GetFrame()->GetWindow() ) );
+    GMenuModel* pMenuModel = G_MENU_MODEL( g_object_get_data( G_OBJECT( gdkWindow ), "g-lo-menubar" ) );
+    GActionGroup* pActionGroup = G_ACTION_GROUP( g_object_get_data( G_OBJECT( gdkWindow ), "g-lo-action-group" ) );
 
-        // Some items are special, so they have different commands.
-        if ( g_strcmp0( aNativeCommand, "" ) == 0 )
+    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.
+    GDBusConnection* pSessionBus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
+
+    if( pSessionBus == NULL ) {
+        cout << "Failed to get session bus" << endl;
+        return FALSE;
+    }
+
+    // Publish the menu.
+    if ( aDBusMenubarPath != NULL && pMenuModel != NULL )
+        g_dbus_connection_export_menu_model (pSessionBus, aDBusMenubarPath, pMenuModel, NULL);
+
+    if ( aDBusPath != NULL && pActionGroup != NULL )
+        g_dbus_connection_export_action_group( pSessionBus, aDBusPath, pActionGroup, NULL);
+
+    // Set window properties.
+    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 );
+    gdk_x11_window_set_utf8_property ( gdkWindow, "_GTK_MENUBAR_OBJECT_PATH", aDBusMenubarPath );
+
+    g_free( aDBusPath );
+    g_free( aDBusWindowPath );
+    g_free( aDBusMenubarPath );
+
+    return FALSE;
+}
+
+static void UpdateNativeMenu( GtkSalMenu* pMenu );
+gboolean GenerateMenu( gpointer user_data );
+
+static void on_registrar_available( GDBusConnection* /*connection*/,
+                                    const gchar*     /*name*/,
+                                    const gchar*     /*name_owner*/,
+                                    gpointer         user_data )
+{
+    GtkSalFrame* pSalFrame = static_cast< GtkSalFrame* >( user_data );
+    GtkSalMenu* pSalMenu = static_cast< GtkSalMenu* >( pSalFrame->GetMenu() );
+
+    if ( pSalMenu != NULL )
+    {
+        MenuBar* pMenuBar = static_cast< MenuBar* >( pSalMenu->GetMenu() );
+
+        GtkWidget *pWidget = pSalFrame->getWindow();
+        GdkWindow *gdkWindow = gtk_widget_get_window( pWidget );
+
+        if ( gdkWindow != NULL )
         {
-            gchar *aSpecialItemCmd = GetCommandForSpecialItem( pSalMenuItem );
+            GMenuModel* pMenuModel = G_MENU_MODEL( g_object_get_data( G_OBJECT( gdkWindow ), "g-lo-menubar" ) );
 
-            if ( aSpecialItemCmd != NULL )
+            if ( pMenuModel == NULL )
             {
-                g_free( aNativeCommand );
-                aNativeCommand = aSpecialItemCmd;
+                pMenuModel = G_MENU_MODEL( g_lo_menu_new() );
+                g_object_set_data_full( G_OBJECT( gdkWindow ), "g-lo-menubar", pMenuModel, ObjectDestroyedNotify );
+                pSalMenu->SetMenuModel( pMenuModel );
             }
+
+            GActionGroup* pActionGroup = G_ACTION_GROUP( g_object_get_data( G_OBJECT( gdkWindow ), "g-lo-action-group" ) );
+
+            if ( pActionGroup == NULL )
+            {
+                pActionGroup = G_ACTION_GROUP( g_lo_action_group_new( pSalFrame ) );
+                g_object_set_data_full( G_OBJECT( gdkWindow ), "g-lo-action-group", pActionGroup, ObjectDestroyedNotify );
+                pSalMenu->SetActionGroup( pActionGroup );
+            }
+
+//            PublishMenu( gdkWindow );
+//            g_idle_add_full( G_PRIORITY_HIGH_IDLE, PublishMenu, (gpointer) gdkWindow, NULL );
+//            g_timeout_add_full( G_PRIORITY_HIGH, 0, PublishMenu, (gpointer) gdkWindow, NULL );
+            gdk_threads_add_timeout_full( G_PRIORITY_HIGH, 0, PublishMenu, (gpointer) gdkWindow, NULL );
+
+            bDBusIsAvailable = sal_True;
+
+            if ( pMenuBar )
+                pMenuBar->SetDisplayable( sal_False );
+
+//            GenerateMenu( pSalMenu );
+//            g_idle_add_full( G_PRIORITY_HIGH_IDLE, GenerateMenu, pSalMenu, NULL );
+//            g_timeout_add_full( G_PRIORITY_HIGH, 0, GenerateMenu, pSalMenu, NULL );
+            gdk_threads_add_timeout_full( G_PRIORITY_HIGH, 0, GenerateMenu, pSalMenu, NULL );
+//            UpdateNativeMenu( pSalMenu );
+//            UpdateNativeSubMenu( pSalMenu );
         }
+    }
+}
 
-        if ( g_strcmp0( aNativeCommand, "" ) != 0 && pSalMenuItem->mpSubMenu == NULL )
+// This is called when the registrar becomes unavailable. It shows the menubar.
+static void on_registrar_unavailable( GDBusConnection * /*connection*/,
+                                      const gchar     * /*name*/,
+                                      gpointer          user_data )
+{
+    GtkSalFrame* pSalFrame = static_cast< GtkSalFrame* >( user_data );
+    GtkSalMenu* pSalMenu = static_cast< GtkSalMenu* >( pSalFrame->GetMenu() );
+
+    if ( pSalMenu ) {
+        MenuBar* pMenuBar = static_cast< MenuBar* >( pSalMenu->GetMenu() );
+
+        bDBusIsAvailable = sal_False;
+        pMenuBar->SetDisplayable( sal_True );
+    }
+}
+
+/*
+ * Native menu methods
+ */
+
+//static void InitNativeMenu( GtkSalFrame* pFrame )
+static gboolean InitNativeMenu( gpointer user_data )
+{
+    GtkSalFrame* pFrame = (GtkSalFrame*) user_data;
+
+    // Publish the menu only if AppMenu registrar is available.
+    guint 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,
+                                         (gpointer) pFrame,
+                                         NULL);
+
+    pFrame->SetWatcherId( nWatcherId );
+    return FALSE;
+}
+
+static void NativeCheckItem( GLOMenu*        pMenu,
+                             GLOActionGroup* pActionGroup,
+                             unsigned        nSection,
+                             unsigned        nItemPos,
+                             MenuItemBits    bits,
+                             gboolean        bCheck )
+{
+    if ( pActionGroup == NULL )
+        return;
+
+    gchar* aCommand = g_lo_menu_get_command_from_item_in_section( pMenu, nSection, nItemPos );
+
+    if ( aCommand != NULL || g_strcmp0( aCommand, "" ) != 0 )
+    {
+        GVariant *pCheckValue = NULL;
+        GVariant *pCurrentState = g_action_group_get_action_state( G_ACTION_GROUP( pActionGroup ), aCommand );
+
+        if ( bits & MIB_RADIOCHECK )
+        {
+            pCheckValue = ( bCheck == TRUE ) ? g_variant_new_string( aCommand ) : g_variant_new_string( "" );
+        }
+        else
         {
-            pMenu->NativeSetItemCommand( nSection, nItemPos, nId, aNativeCommand, itemBits, bChecked, FALSE );
-            pMenu->NativeCheckItem( nSection, nItemPos, itemBits, bChecked );
-            pMenu->NativeSetEnableItem( aNativeCommand, bEnabled );
+            // By default, all checked items are checkmark buttons.
+            if ( bCheck == TRUE || ( ( bCheck == FALSE ) && pCurrentState != NULL ) )
+                pCheckValue = g_variant_new_boolean( bCheck );
         }
 
-        GtkSalMenu* pSubmenu = pSalMenuItem->mpSubMenu;
+        if ( pCheckValue != NULL && ( pCurrentState == NULL || g_variant_equal( pCurrentState, pCheckValue ) == FALSE ) )
+            g_action_group_change_action_state( G_ACTION_GROUP( pActionGroup ), aCommand, pCheckValue );
 
-        if ( pSubmenu && pSubmenu->GetMenu() )
-        {
-            pMenu->NativeSetItemCommand( nSection, nItemPos, nId, aNativeCommand, itemBits, FALSE, TRUE );
+        if ( pCurrentState )
+            g_variant_unref( pCurrentState );
+    }
 
-            GLOMenu* pSubMenuModel = g_lo_menu_get_submenu_from_item_in_section( pLOMenu, nSection, nItemPos );
+    if ( aCommand )
+        g_free( aCommand );
+}
 
-            if ( pSubMenuModel == NULL )
-            {
-                pSubMenuModel = g_lo_menu_new();
-                g_lo_menu_set_submenu_to_item_in_section( pLOMenu, nSection, nItemPos, G_MENU_MODEL( pSubMenuModel ) );
-            }
+static void NativeSetEnableItem( GLOActionGroup* pActionGroup,
+                                 gchar*          aCommand,
+                                 gboolean        bEnable )
+{
+    if ( g_action_group_get_action_enabled( G_ACTION_GROUP( pActionGroup ), aCommand ) != bEnable )
+        g_lo_action_group_set_action_enabled( pActionGroup, aCommand, bEnable );
+}
 
-            g_object_unref( pSubMenuModel );
+static void NativeSetItemText( GLOMenu*             pMenu,
+                               unsigned             nSection,
+                               unsigned             nItemPos,
+                               const rtl::OUString& rText )
+{
+    // Replace the '~' character with '_'.
+    rtl::OUString aText = rText.replace( '~', '_' );
+    rtl::OString aConvertedText = OUStringToOString( aText, RTL_TEXTENCODING_UTF8 );
 
-            pSubmenu->SetMenuModel( G_MENU_MODEL( pSubMenuModel ) );
-            pSubmenu->SetActionGroup( pActionGroup );
+    // Update item text only when necessary.
+    gchar* aLabel = g_lo_menu_get_label_from_item_in_section( pMenu, nSection, nItemPos );
+
+    if ( aLabel == NULL || g_strcmp0( aLabel, aConvertedText.getStr() ) != 0 )
+        g_lo_menu_set_label_to_item_in_section( pMenu, nSection, nItemPos, aConvertedText.getStr() );
+
+    if ( aLabel )
+        g_free( aLabel );
+}
+
+static void NativeSetAccelerator( GLOMenu*             pMenu,
+                                  unsigned             nSection,
+                                  unsigned             nItemPos,
+                                  const KeyCode&       /* rKeyCode */,
+                                  const rtl::OUString& rKeyName )
+{
+    if ( rKeyName.isEmpty() )
+        return;
+
+    rtl::OString aAccelerator = rtl::OUStringToOString( GetGtkKeyName( rKeyName ), RTL_TEXTENCODING_UTF8 );
+
+    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 ( pMenu, nSection, nItemPos, aAccelerator.getStr() );
+
+    if ( aCurrentAccel )
+        g_free( aCurrentAccel );
+}
+
+static void NativeSetItemCommand( GLOMenu*        pMenu,
+                                  GLOActionGroup* pActionGroup,
+                                  unsigned        nSection,
+                                  unsigned        nItemPos,
+                                  sal_uInt16      nId,
+                                  const gchar*    aCommand,
+                                  MenuItemBits    nBits,
+                                  gboolean        bChecked,
+                                  gboolean        bIsSubmenu )
+{
+    GVariant *pTarget = NULL;
+
+    if ( g_action_group_has_action( G_ACTION_GROUP( pActionGroup ), aCommand ) == FALSE ) {
+        if ( ( nBits & MIB_CHECKABLE ) || ( bIsSubmenu == TRUE ) )
+        {
+            // Item is a checkmark button.
+            GVariantType* pStateType = g_variant_type_new( (gchar*) G_VARIANT_TYPE_BOOLEAN );
+            GVariant* pState = g_variant_new_boolean( bChecked );
+
+            g_lo_action_group_insert_stateful( pActionGroup, aCommand, nId, bIsSubmenu, NULL, pStateType, NULL, pState );
         }
+        else if ( nBits & MIB_RADIOCHECK )
+        {
+            // Item is a radio button.
+            GVariantType* pParameterType = g_variant_type_new( (gchar*) G_VARIANT_TYPE_STRING );
+            GVariantType* pStateType = g_variant_type_new( (gchar*) G_VARIANT_TYPE_STRING );
+            GVariant* pState = g_variant_new_string( "" );
+            pTarget = g_variant_new_string( aCommand );
 
-        g_free( aNativeCommand );
+            g_lo_action_group_insert_stateful( pActionGroup, aCommand, nId, FALSE, pParameterType, pStateType, NULL, pState );
+        }
+        else
+        {
+            // Item is not special, so insert a stateless action.
+            g_lo_action_group_insert( pActionGroup, aCommand, nId, FALSE );
+        }
+    }
 
-        nItemPos++;
-        validItems++;
+    // Menu item is not updated unless it's necessary.
+    gchar* aCurrentCommand = g_lo_menu_get_command_from_item_in_section( pMenu, nSection, nItemPos );
+
+    if ( aCurrentCommand == NULL || g_strcmp0( aCurrentCommand, aCommand ) != 0 )
+    {
+        g_lo_menu_set_command_to_item_in_section( pMenu, nSection, nItemPos, aCommand );
+
+        gchar* aItemCommand = g_strconcat("win.", aCommand, NULL );
+
+        if ( bIsSubmenu == TRUE )
+            g_lo_menu_set_submenu_action_to_item_in_section( pMenu, nSection, nItemPos, aItemCommand );
+        else
+            g_lo_menu_set_action_and_target_value_to_item_in_section( pMenu, nSection, nItemPos, aItemCommand, pTarget );
+
+        g_free( aItemCommand );
     }
+
+    if ( aCurrentCommand )
+        g_free( aCurrentCommand );
 }
 
-static void UpdateNativeMenu( GtkSalMenu* pMenu )
+/*
+ * Menu updating methods
+ */
+
+static void UpdateNativeSubMenu( GtkSalMenu *pMenu )
 {
     if ( pMenu == NULL )
         return;
 
+//    SolarMutexGuard aGuard;
+
     Menu* pVCLMenu = pMenu->GetMenu();
     GLOMenu* pLOMenu = G_LO_MENU( pMenu->GetMenuModel() );
-    GActionGroup* pActionGroup = pMenu->GetActionGroup();
+    GLOActionGroup* pActionGroup = G_LO_ACTION_GROUP( pMenu->GetActionGroup() );
 
     sal_uInt16 nLOMenuSize = g_menu_model_get_n_items( G_MENU_MODEL( pLOMenu ) );
 
@@ -207,8 +455,8 @@ static void UpdateNativeMenu( GtkSalMenu* pMenu )
         gchar* aNativeCommand = g_strdup( rtl::OUStringToOString( aCommand, RTL_TEXTENCODING_UTF8 ).getStr() );
 
         // Force updating of native menu labels.
-        pMenu->NativeSetItemText( nSection, nItemPos, aText );
-        pMenu->NativeSetAccelerator( nSection, nItemPos, nAccelKey, nAccelKey.GetName( pMenu->GetFrame()->GetWindow() ) );
+        NativeSetItemText( pLOMenu, nSection, nItemPos, aText );
+        NativeSetAccelerator( pLOMenu, nSection, nItemPos, nAccelKey, nAccelKey.GetName( pMenu->GetFrame()->GetWindow() ) );
 
         // Some items are special, so they have different commands.
         if ( g_strcmp0( aNativeCommand, "" ) == 0 )
@@ -224,16 +472,16 @@ static void UpdateNativeMenu( GtkSalMenu* pMenu )
 
         if ( g_strcmp0( aNativeCommand, "" ) != 0 && pSalMenuItem->mpSubMenu == NULL )
         {
-            pMenu->NativeSetItemCommand( nSection, nItemPos, nId, aNativeCommand, itemBits, bChecked, FALSE );
-            pMenu->NativeCheckItem( nSection, nItemPos, itemBits, bChecked );
-            pMenu->NativeSetEnableItem( aNativeCommand, bEnabled );
+            NativeSetItemCommand( pLOMenu, pActionGroup, nSection, nItemPos, nId, aNativeCommand, itemBits, bChecked, FALSE );
+            NativeCheckItem( pLOMenu, pActionGroup, nSection, nItemPos, itemBits, bChecked );
+            NativeSetEnableItem( pActionGroup, aNativeCommand, bEnabled );
         }
 
         GtkSalMenu* pSubmenu = pSalMenuItem->mpSubMenu;
 
         if ( pSubmenu && pSubmenu->GetMenu() )
         {
-            pMenu->NativeSetItemCommand( nSection, nItemPos, nId, aNativeCommand, itemBits, FALSE, TRUE );
+            NativeSetItemCommand( pLOMenu, pActionGroup, nSection, nItemPos, nId, aNativeCommand, itemBits, FALSE, TRUE );
 
             GLOMenu* pSubMenuModel = g_lo_menu_get_submenu_from_item_in_section( pLOMenu, nSection, nItemPos );
 
@@ -245,12 +493,8 @@ static void UpdateNativeMenu( GtkSalMenu* pMenu )
 
             g_object_unref( pSubMenuModel );
 
-            pSubmenu->GetMenu()->Activate();
-            pSubmenu->GetMenu()->Deactivate();
-
             pSubmenu->SetMenuModel( G_MENU_MODEL( pSubMenuModel ) );
-            pSubmenu->SetActionGroup( pActionGroup );
-            UpdateNativeMenu( pSubmenu );
+            pSubmenu->SetActionGroup( G_ACTION_GROUP( pActionGroup ) );
         }
 
         g_free( aNativeCommand );
@@ -260,156 +504,75 @@ static void UpdateNativeMenu( GtkSalMenu* pMenu )
     }
 }
 
-gboolean GenerateMenu(gpointer user_data)
-{
-    GtkSalMenu* pSalMenu = static_cast< GtkSalMenu* >( user_data );
-
-    UpdateNativeMenu( pSalMenu );
-
-    return TRUE;
-}
-
-void ObjectDestroyedNotify( gpointer data )
-{
-    if ( data ) {
-        g_object_unref( data );
-    }
-}
-
-void
-gdk_x11_window_set_utf8_property  (GdkWindow *window,
-                                   const gchar *name,
-                                   const gchar *value)
-{
-  GdkDisplay *display;
-
-  //if (!WINDOW_IS_TOPLEVEL (window))
-    //return;
-
-  display = gdk_window_get_display (window);
-
-  if (value != NULL)
-    {
-      XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
-                       GDK_WINDOW_XID (window),
-                       gdk_x11_get_xatom_by_name_for_display (display, name),
-                       gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
-                       PropModeReplace, (guchar *)value, strlen (value));
-    }
-  else
-    {
-      XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
-                       GDK_WINDOW_XID (window),
-                       gdk_x11_get_xatom_by_name_for_display (display, name));
-    }
-}
-
-// FIXME: Check for missing keys. Maybe translating keycodes would be safer...
-rtl::OUString GetGtkKeyName( rtl::OUString keyName )
+static void UpdateNativeMenu( GtkSalMenu* pMenu )
 {
-    rtl::OUString aGtkKeyName("");
-
-    sal_Int32 nIndex = 0;
-
-    do
-    {
-        rtl::OUString token = keyName.getToken( 0, '+', nIndex );
+//    if ( pMenu == NULL )
+//        return;
 
-        if ( token == "Ctrl" ) {
-            aGtkKeyName += "<Control>";
-        } else if ( token == "Alt" ) {
-            aGtkKeyName += "<Alt>";
-        } else if ( token == "Shift" ) {
-            aGtkKeyName += "<Shift>";
-        } else {
-            aGtkKeyName += token;
-        }
-    } while ( nIndex >= 0 );
+//    UpdateNativeSubMenu( pMenu );
 
-    return aGtkKeyName;
-}
+//    for ( sal_uInt16 nItem = 0; nItem < pMenu->GetItemCount(); nItem++ ) {
+//        GtkSalMenuItem *pSalMenuItem = pMenu->GetItemAtPos( nItem );
 
-// AppMenu watch functions.
+//        if ( pSalMenuItem->mnType == MENUITEM_SEPARATOR )
+//            continue;
 
-static sal_Bool bDBusIsAvailable = sal_False;
+//        GtkSalMenu* pSubmenu = pSalMenuItem->mpSubMenu;
 
-static void
-on_registrar_available (GDBusConnection * /*connection*/,
-                        const gchar     * /*name*/,
-                        const gchar     * /*name_owner*/,
-                        gpointer         user_data)
-{
-    GtkSalFrame* pSalFrame = static_cast< GtkSalFrame* >( user_data );
-    GtkSalMenu* pSalMenu = static_cast< GtkSalMenu* >( pSalFrame->GetMenu() );
+//        if ( pSubmenu != NULL && pSubmenu->GetMenu() != NULL )
+//        {
+////            pSubmenu->GetMenu()->Activate();
+//            Link aActivateHdl = pSubmenu->GetMenu()->GetActivateHdl();
+//            aActivateHdl.Call( pSubmenu->GetMenu() );
 
-    if ( pSalMenu != NULL )
-    {
-        MenuBar* pMenuBar = static_cast< MenuBar* >( pSalMenu->GetMenu() );
+////            cout << "Activate" << endl;
 
-        GtkWidget *pWidget = pSalFrame->getWindow();
-        GdkWindow *gdkWindow = gtk_widget_get_window( pWidget );
+//            Link aDeactivateHdl = pSubmenu->GetMenu()->GetDeactivateHdl();
+//            aDeactivateHdl.Call( pSubmenu->GetMenu() );
 
-        if ( gdkWindow != NULL )
-        {
-            GMenuModel* pMenuModel = G_MENU_MODEL( g_object_get_data( G_OBJECT( gdkWindow ), "g-lo-menubar" ) );
-            GActionGroup* pActionGroup = G_ACTION_GROUP( g_object_get_data( G_OBJECT( gdkWindow ), "g-lo-action-group" ) );
+////            cout << "Deactivate" << endl;
 
-            XLIB_Window windowId = GDK_WINDOW_XID( gdkWindow );
+////                        pSubmenu->GetMenu()->Deactivate();
+//            UpdateNativeSubMenu( pSubmenu );
 
-            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 );
+////            cout << "Updated" << endl;
 
-            // Get a DBus session connection.
-            GDBusConnection* pSessionBus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
+//        }
+//    }
 
-            if( pSessionBus == NULL )
-                return;
+    SolarMutexGuard aGuard;
 
-            // Publish the menu.
-            if ( aDBusMenubarPath != NULL && pMenuModel != NULL )
-                g_dbus_connection_export_menu_model (pSessionBus, aDBusMenubarPath, pMenuModel, NULL);
+    GLOMenu *pLOMenu = G_LO_MENU( pMenu->GetMenuModel() );
+    GLOActionGroup * pLOActionGroup = G_LO_ACTION_GROUP( pMenu->GetActionGroup() );
 
-            if ( aDBusPath != NULL && pActionGroup != NULL )
-                g_dbus_connection_export_action_group( pSessionBus, aDBusPath, pActionGroup, NULL);
+    g_lo_menu_new_section( pLOMenu, 0, NULL );
 
-            // Set window properties.
-            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 );
-            gdk_x11_window_set_utf8_property ( gdkWindow, "_GTK_MENUBAR_OBJECT_PATH", aDBusMenubarPath );
+    for ( int i=0; i < 9; i++ ) {
+        gchar* menuStr = g_strdup_printf("Menu%d", i);
 
-            g_free( aDBusPath );
-            g_free( aDBusWindowPath );
-            g_free( aDBusMenubarPath );
+        g_lo_menu_insert_in_section( pLOMenu, 0, i, menuStr);
 
-            bDBusIsAvailable = sal_True;
+        g_free(menuStr);
 
-            if ( pMenuBar )
-                pMenuBar->SetDisplayable( sal_False );
-        }
+        GLOMenu *pLOMenu1 = g_lo_menu_new();
+        g_lo_menu_set_submenu_to_item_in_section( pLOMenu, 0, i, G_MENU_MODEL( pLOMenu1 ) );
+        g_lo_menu_new_section( pLOMenu1, 0, NULL );
+        g_lo_menu_insert_in_section( pLOMenu1, 0, 0, "Option1" );
+        g_lo_menu_insert_in_section( pLOMenu1, 0, 1, "Option2" );
+        g_lo_menu_insert_in_section( pLOMenu1, 0, 2, "Option3" );
+        g_lo_menu_insert_in_section( pLOMenu1, 0, 3, "Option4" );
     }
 
-    return;
 }
 
-//This is called when the registrar becomes unavailable. It shows the menubar.
-static void
-on_registrar_unavailable (GDBusConnection * /*connection*/,
-                          const gchar     * /*name*/,
-                          gpointer         user_data)
+gboolean GenerateMenu( gpointer user_data )
 {
-    GtkSalFrame* pSalFrame = static_cast< GtkSalFrame* >( user_data );
-    GtkSalMenu* pSalMenu = static_cast< GtkSalMenu* >( pSalFrame->GetMenu() );
-
-    if ( pSalMenu ) {
-        MenuBar* pMenuBar = static_cast< MenuBar* >( pSalMenu->GetMenu() );
+    GtkSalMenu* pSalMenu = static_cast< GtkSalMenu* >( user_data );
 
-        bDBusIsAvailable = sal_False;
-        pMenuBar->SetDisplayable( sal_True );
-    }
+//    SolarMutexGuard aGuard;
+    UpdateNativeMenu( pSalMenu );
 
-    return;
+    return FALSE;
 }
 
 /*
@@ -431,8 +594,6 @@ GtkSalMenu::GtkSalMenu( sal_Bool bMenuBar ) :
 GtkSalMenu::~GtkSalMenu()
 {
     if ( mbMenuBar == sal_True ) {
-//        g_source_remove_by_user_data( this );
-
         ((GtkSalFrame*) mpFrame)->SetMenu( NULL );
 
         if ( mpActionGroup ) {
@@ -469,7 +630,7 @@ void GtkSalMenu::RemoveItem( unsigned nPos )
     maItems.erase( maItems.begin() + nPos );
 }
 
-void GtkSalMenu::SetSubMenu( SalMenuItem* pSalMenuItem, SalMenu* pSubMenu, unsigned nPos )
+void GtkSalMenu::SetSubMenu( SalMenuItem* pSalMenuItem, SalMenu* pSubMenu, unsigned )
 {
     GtkSalMenuItem *pItem = static_cast< GtkSalMenuItem* >( pSalMenuItem );
     GtkSalMenu *pGtkSubMenu = static_cast< GtkSalMenu* >( pSubMenu );
@@ -495,32 +656,15 @@ void GtkSalMenu::SetFrame( const SalFrame* pFrame )
         mpMenuModel = G_MENU_MODEL( g_object_get_data( G_OBJECT( gdkWindow ), "g-lo-menubar" ) );
         mpActionGroup = G_ACTION_GROUP( g_object_get_data( G_OBJECT( gdkWindow ), "g-lo-action-group" ) );
 
-        if ( mpMenuModel == NULL && mpActionGroup == NULL ) {
-            mpMenuModel = G_MENU_MODEL( g_lo_menu_new() );
-            mpActionGroup = G_ACTION_GROUP( g_lo_action_group_new( ( gpointer ) mpFrame ) );
-
-            g_object_set_data_full( G_OBJECT( gdkWindow ), "g-lo-menubar", mpMenuModel, ObjectDestroyedNotify );
-            g_object_set_data_full( G_OBJECT( gdkWindow ), "g-lo-action-group", mpActionGroup, ObjectDestroyedNotify );
-
-            // Publish the menu only if AppMenu registrar is available.
-            guint 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,
-                                                 (gpointer) mpFrame,
-                                                 NULL);
-
-            ( ( GtkSalFrame* ) mpFrame )->SetWatcherId( nWatcherId );
-        }
-
-        // Generate the main menu structure.
-        GenerateMenu( this );
-//        UpdateNativeMenu2( this );
-
-        // Refresh the menu every second.
-        // This code is a workaround until required modifications in Gtk+ are available.
-//        g_timeout_add_seconds( 1, GenerateMenu, this );
+        if ( mpMenuModel == NULL && mpActionGroup == NULL )
+//            InitNativeMenu( ( GtkSalFrame* ) pFrame );
+//            g_idle_add_full( G_PRIORITY_HIGH_IDLE, InitNativeMenu, (gpointer) pFrame, NULL );
+//            g_timeout_add_full( G_PRIORITY_HIGH, 0, InitNativeMenu, (gpointer) pFrame, NULL );
+            gdk_threads_add_timeout_full( G_PRIORITY_HIGH, 0, InitNativeMenu, (gpointer) pFrame, NULL );
+        else
+            // Generate the main menu structure.
+            GenerateMenu( this );
+//            UpdateNativeMenu( this );
     }
 }
 
@@ -532,141 +676,6 @@ const GtkSalFrame* GtkSalMenu::GetFrame() const
     return pMenu ? pMenu->mpFrame : NULL;
 }
 
-void GtkSalMenu::NativeCheckItem( unsigned nSection, unsigned nItemPos, MenuItemBits bits, gboolean bCheck )
-{
-    if ( mpActionGroup == NULL )
-        return;
-
-    gchar* aCommand = g_lo_menu_get_command_from_item_in_section( G_LO_MENU( mpMenuModel ), nSection, nItemPos );
-
-    if ( aCommand != NULL || g_strcmp0( aCommand, "" ) != 0 )
-    {
-        GVariant *pCheckValue = NULL;
-        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.
-            if ( bCheck == TRUE || ( ( bCheck == FALSE ) && pCurrentState != NULL ) )
-                pCheckValue = g_variant_new_boolean( bCheck );
-        }
-
-        if ( pCheckValue != NULL && ( pCurrentState == NULL || g_variant_equal( pCurrentState, pCheckValue ) == FALSE ) )
-            g_action_group_change_action_state( mpActionGroup, aCommand, pCheckValue );
-
-        if ( pCurrentState )
-            g_variant_unref( pCurrentState );
-    }
-
-    if ( aCommand )
-        g_free( aCommand );
-}
-
-void GtkSalMenu::NativeSetEnableItem( gchar* aCommand, gboolean bEnable )
-{
-    GLOActionGroup* pActionGroup = G_LO_ACTION_GROUP( mpActionGroup );
-
-    if ( g_action_group_get_action_enabled( G_ACTION_GROUP( pActionGroup ), aCommand ) != bEnable )
-        g_lo_action_group_set_action_enabled( pActionGroup, aCommand, bEnable );
-}
-
-void GtkSalMenu::NativeSetItemText( unsigned nSection, unsigned nItemPos, const rtl::OUString& rText )
-{
-    // Replace the '~' character with '_'.
-    rtl::OUString aText = rText.replace( '~', '_' );
-    rtl::OString aConvertedText = OUStringToOString( aText, RTL_TEXTENCODING_UTF8 );
-
-    // Update item text only when necessary.
-    gchar* aLabel = g_lo_menu_get_label_from_item_in_section( G_LO_MENU( mpMenuModel ), nSection, nItemPos );
-
-    if ( aLabel == NULL || g_strcmp0( aLabel, aConvertedText.getStr() ) != 0 )
-        g_lo_menu_set_label_to_item_in_section( G_LO_MENU( mpMenuModel ), nSection, nItemPos, aConvertedText.getStr() );
-
-    if ( aLabel )
-        g_free( aLabel );
-}
-
-void GtkSalMenu::NativeSetAccelerator( unsigned nSection, unsigned nItemPos, const KeyCode& rKeyCode, const rtl::OUString& rKeyName )
-{
-    if ( rKeyName.isEmpty() )
-        return;
-
-    rtl::OString aAccelerator = rtl::OUStringToOString( GetGtkKeyName( rKeyName ), RTL_TEXTENCODING_UTF8 );
-
-    gchar* aCurrentAccel = g_lo_menu_get_accelerator_from_item_in_section( G_LO_MENU( mpMenuModel ), 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 )
-        g_free( aCurrentAccel );
-}
-
-void GtkSalMenu::NativeSetItemCommand( unsigned nSection,
-                                       unsigned nItemPos,
-                                       sal_uInt16 nId,
-                                       const gchar* aCommand,
-                                       MenuItemBits nBits,
-                                       gboolean bChecked,
-                                       gboolean bIsSubmenu )
-{
-    GLOActionGroup* pActionGroup = G_LO_ACTION_GROUP( mpActionGroup );
-
-    GVariant *pTarget = NULL;
-
-    if ( g_action_group_has_action( mpActionGroup, aCommand ) == FALSE ) {
-        if ( ( nBits & MIB_CHECKABLE ) || ( bIsSubmenu == TRUE ) )
-        {
-            // Item is a checkmark button.
-            GVariantType* pStateType = g_variant_type_new( (gchar*) G_VARIANT_TYPE_BOOLEAN );
-            GVariant* pState = g_variant_new_boolean( bChecked );
-
-            g_lo_action_group_insert_stateful( pActionGroup, aCommand, nId, bIsSubmenu, NULL, pStateType, NULL, pState );
-        }
-        else if ( nBits & MIB_RADIOCHECK )
-        {
-            // Item is a radio button.
-            GVariantType* pParameterType = g_variant_type_new( (gchar*) G_VARIANT_TYPE_STRING );
-            GVariantType* pStateType = g_variant_type_new( (gchar*) G_VARIANT_TYPE_STRING );
-            GVariant* pState = g_variant_new_string( "" );
-            pTarget = g_variant_new_string( aCommand );
-
-            g_lo_action_group_insert_stateful( pActionGroup, aCommand, nId, FALSE, pParameterType, pStateType, NULL, pState );
-        }
-        else
-        {
-            // Item is not special, so insert a stateless action.
-            g_lo_action_group_insert( pActionGroup, aCommand, nId, FALSE );
-        }
-    }
-
-    GLOMenu* pMenu = G_LO_MENU( mpMenuModel );
-
-    // Menu item is not updated unless it's necessary.
-    gchar* aCurrentCommand = g_lo_menu_get_command_from_item_in_section( pMenu, nSection, nItemPos );
-
-    if ( aCurrentCommand == NULL || g_strcmp0( aCurrentCommand, aCommand ) != 0 )
-    {
-        g_lo_menu_set_command_to_item_in_section( pMenu, nSection, nItemPos, aCommand );
-
-        gchar* aItemCommand = g_strconcat("win.", aCommand, NULL );
-
-        if ( bIsSubmenu == TRUE )
-            g_lo_menu_set_submenu_action_to_item_in_section( pMenu, nSection, nItemPos, aItemCommand );
-        else
-            g_lo_menu_set_action_and_target_value_to_item_in_section( pMenu, nSection, nItemPos, aItemCommand, pTarget );
-
-        g_free( aItemCommand );
-    }
-
-    if ( aCurrentCommand )
-        g_free( aCurrentCommand );
-}
-
 GtkSalMenu* GtkSalMenu::GetMenuForItemCommand( gchar* aCommand, gboolean bGetSubmenu )
 {
     GtkSalMenu* pMenu = NULL;
@@ -719,7 +728,7 @@ void GtkSalMenu::Activate( const gchar* aMenuCommand )
 
     if ( pSalSubMenu != NULL ) {
         pSalSubMenu->mpVCLMenu->Activate();
-        UpdateNativeMenu2( pSalSubMenu );
+        UpdateNativeSubMenu( pSalSubMenu );
     }
 }
 
@@ -735,31 +744,31 @@ void GtkSalMenu::Deactivate( const gchar* aMenuCommand )
     }
 }
 
-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 )
 {
 }
 
-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* )
 {
 }
 


More information about the Libreoffice-commits mailing list