[SCM] LibreOffice packaging repository branch, ubuntu-quantal-3.6, updated. libreoffice_3.5.4-5-172-g899d9d2
The following commit has been merged in the ubuntu-quantal-3.6 branch:
commit f409c6cd1d3a2bc91e1578cbe551854ee1030c3c
Author: Bjoern Michaelsen <bjoern.michaelsen@canonical.com>
Date: Fri Aug 17 17:07:14 2012 +0200
enable unitymenu patch
diff --git a/changelog b/changelog
index 105e128..909f0f3 100644
--- a/changelog
+++ b/changelog
@@ -13,6 +13,7 @@ libreoffice (1:3.6.0~rc4-0ubuntu3~ppa1) precise; urgency=low
- remove unoapi-test disabling patch, now that we seem to evade lp#1017125
* reenable reportbuilder for universe ppa builds only (LP: #992232)
* add packagekit patch
+ * add unitymenus patch
-- Bjoern Michaelsen <bjoern.michaelsen@canonical.com> Tue, 21 Aug 2012 02:46:51 +0200
diff --git a/patches/series b/patches/series
index 47617a9..1fb35d6 100644
--- a/patches/series
+++ b/patches/series
@@ -30,3 +30,4 @@ lp-753627-readd-updated-Ubuntu-brand-palette-colors.diff
remove-broken-mysqlcon-version-check.diff
fdo-51324-lp-1017125-rhbz-806236-rhbz-823272-erase-o.diff
packagekit.diff
+unitymenus.diff
diff --git a/patches/unitymenus.diff b/patches/unitymenus.diff
new file mode 100644
index 0000000..861a9ff
--- /dev/null
+++ b/patches/unitymenus.diff
@@ -0,0 +1,2827 @@
+commit 5e07b8e29fc3f0cf61edf8478e686f593c89105b
+Author: Antonio Fernandez <antonio.fernandez@aentos.es>
+Date: Mon Aug 20 09:44:24 2012 +0100
+
+ Actions are generated during the item info filling.
+
+ Change-Id: I79be19a8ca565da9ca9bb8b31efc4e6e1463ba31
+diff --git a/framework/inc/classes/menumanager.hxx b/framework/inc/classes/menumanager.hxx
+index 3ac4588..56ecc90 100644
+--- a/framework/inc/classes/menumanager.hxx
++++ b/framework/inc/classes/menumanager.hxx
+@@ -78,7 +78,7 @@ class MenuManager : public ThreadHelpBase ,
+ MenuManager(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory,
+ REFERENCE< XFRAME >& rFrame,
+- Menu* pMenu,
++ AbstractMenu* pMenu,
+ sal_Bool bDelete,
+ sal_Bool bDeleteChildren );
+
+@@ -90,33 +90,33 @@ class MenuManager : public ThreadHelpBase ,
+ // XEventListener
+ virtual void SAL_CALL disposing( const EVENTOBJECT& Source ) throw ( RUNTIMEEXCEPTION );
+
+- DECL_LINK( Select, Menu * );
++ DECL_LINK( Select, AbstractMenu * );
+
+- Menu* GetMenu() const { return m_pVCLMenu; }
++ AbstractMenu* GetMenu() const { return m_pVCLMenu; }
+
+ void RemoveListener();
+
+ const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& getServiceFactory();
+
+- static void UpdateSpecialWindowMenu( Menu* pMenu ,const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory,IMutex& _rMutex);
++ static void UpdateSpecialWindowMenu( AbstractMenu* pMenu ,const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory,IMutex& _rMutex);
+ static void FillMenuImages(
+ ::com::sun::star::uno::Reference< com::sun::star::frame::XFrame >& xFrame,
+- Menu* _pMenu,
++ AbstractMenu* _pMenu,
+ sal_Bool bShowMenuImages
+ );
+
+ protected:
+ DECL_LINK(Highlight, void *);
+- DECL_LINK( Activate, Menu * );
+- DECL_LINK( Deactivate, Menu * );
++ DECL_LINK( Activate, AbstractMenu * );
++ DECL_LINK( Deactivate, AbstractMenu * );
+
+ private:
+- void UpdateSpecialFileMenu( Menu* pMenu );
+- void UpdateSpecialWindowMenu( Menu* pMenu );
++ void UpdateSpecialFileMenu( AbstractMenu* pMenu );
++ void UpdateSpecialWindowMenu( AbstractMenu* pMenu );
+ void ClearMenuDispatch(const EVENTOBJECT& Source = EVENTOBJECT(),bool _bRemoveOnly = true);
+ void SetHdl();
+ void AddMenu(PopupMenu* _pPopupMenu,const ::rtl::OUString& _sItemCommand,sal_uInt16 _nItemId,sal_Bool _bDelete,sal_Bool _bDeleteChildren);
+- sal_uInt16 FillItemCommand(::rtl::OUString& _rItemCommand,Menu* _pMenu,sal_uInt16 _nIndex) const;
++ sal_uInt16 FillItemCommand(::rtl::OUString& _rItemCommand, AbstractMenu* _pMenu,sal_uInt16 _nIndex) const;
+
+
+ struct MenuItemHandler
+@@ -147,7 +147,7 @@ class MenuManager : public ThreadHelpBase ,
+ sal_Bool m_bIsBookmarkMenu;
+ sal_Bool m_bShowMenuImages;
+ ::rtl::OUString m_aMenuItemCommand;
+- Menu* m_pVCLMenu;
++ AbstractMenu* m_pVCLMenu;
+ REFERENCE< XFRAME > m_xFrame;
+ ::std::vector< MenuItemHandler* > m_aMenuItemHandlerVector;
+
+diff --git a/framework/inc/uielement/menubarmanager.hxx b/framework/inc/uielement/menubarmanager.hxx
+index 6836707..59273e8 100644
+--- a/framework/inc/uielement/menubarmanager.hxx
++++ b/framework/inc/uielement/menubarmanager.hxx
+@@ -120,7 +120,7 @@ class MenuBarManager : public com::sun::star::frame::XStatusListener
+ const ::com::sun::star::uno::Reference< ::com::sun::star::util::XURLTransformer >& _xURLTransformer,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider >& rDispatchProvider,
+ const rtl::OUString& aModuleIdentifier,
+- Menu* pMenu,
++ AbstractMenu* pMenu,
+ sal_Bool bDelete,
+ sal_Bool bDeleteChildren );
+
+@@ -155,22 +155,22 @@ class MenuBarManager : public com::sun::star::frame::XStatusListener
+ // XSystemDependentMenuPeer
+ virtual ::com::sun::star::uno::Any SAL_CALL getMenuHandle( const ::com::sun::star::uno::Sequence< sal_Int8 >& ProcessId, sal_Int16 SystemType ) throw (::com::sun::star::uno::RuntimeException);
+
+- DECL_LINK( Select, Menu * );
++ DECL_LINK( Select, AbstractMenu * );
+
+- Menu* GetMenuBar() const { return m_pVCLMenu; }
++ AbstractMenu* GetMenuBar() const { return m_pVCLMenu; }
+
+ // Configuration methods
+- static void FillMenuWithConfiguration( sal_uInt16& nId, Menu* pMenu,
++ static void FillMenuWithConfiguration( sal_uInt16& nId, AbstractMenu* pMenu,
+ const ::rtl::OUString& rModuleIdentifier,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess >& rItemContainer,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::util::XURLTransformer >& rTransformer );
+ static void FillMenu( sal_uInt16& nId,
+- Menu* pMenu,
++ AbstractMenu* pMenu,
+ const ::rtl::OUString& rModuleIdentifier,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess >& rItemContainer,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider >& rDispatchProvider );
+
+- void FillMenuManager( Menu* pMenu,
++ void FillMenuManager( AbstractMenu* pMenu,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rFrame,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider >& rDispatchProvider,
+ const rtl::OUString& rModuleIdentifier,
+@@ -181,8 +181,8 @@ class MenuBarManager : public com::sun::star::frame::XStatusListener
+
+ protected:
+ DECL_LINK(Highlight, void *);
+- DECL_LINK( Activate, Menu * );
+- DECL_LINK( Deactivate, Menu * );
++ DECL_LINK( Activate, AbstractMenu * );
++ DECL_LINK( Deactivate, AbstractMenu * );
+ DECL_LINK( AsyncSettingsHdl, Timer * );
+
+ void RemoveListener();
+@@ -225,16 +225,16 @@ class MenuBarManager : public com::sun::star::frame::XStatusListener
+ void CreatePicklistArguments(
+ ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aArgsList,
+ const MenuItemHandler* );
+- void CheckAndAddMenuExtension( Menu* pMenu );
++ void CheckAndAddMenuExtension( AbstractMenu* pMenu );
+ static void impl_RetrieveShortcutsFromConfiguration( const ::com::sun::star::uno::Reference< ::com::sun::star::ui::XAcceleratorConfiguration >& rAccelCfg,
+ const ::com::sun::star::uno::Sequence< rtl::OUString >& rCommands,
+ std::vector< MenuItemHandler* >& aMenuShortCuts );
+- static void MergeAddonMenus( Menu* pMenuBar, const MergeMenuInstructionContainer&, const ::rtl::OUString& aModuleIdentifier );
++ static void MergeAddonMenus( AbstractMenu* pMenuBar, const MergeMenuInstructionContainer&, const ::rtl::OUString& aModuleIdentifier );
+
+ MenuItemHandler* GetMenuItemHandler( sal_uInt16 nItemId );
+ sal_Bool CreatePopupMenuController( MenuItemHandler* pMenuItemHandler );
+ void AddMenu(MenuBarManager* pSubMenuManager,const ::rtl::OUString& _sItemCommand,sal_uInt16 _nItemId);
+- sal_uInt16 FillItemCommand(::rtl::OUString& _rItemCommand,Menu* _pMenu,sal_uInt16 _nIndex) const;
++ sal_uInt16 FillItemCommand(::rtl::OUString& _rItemCommand, AbstractMenu* _pMenu,sal_uInt16 _nIndex) const;
+ void Init(const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rFrame,AddonMenu* pAddonMenu,sal_Bool bDelete,sal_Bool bDeleteChildren,bool _bHandlePopUp = false);
+ void SetHdl();
+
+@@ -250,7 +250,7 @@ class MenuBarManager : public com::sun::star::frame::XStatusListener
+ sal_Bool m_bModuleIdentified;
+ ::rtl::OUString m_aMenuItemCommand;
+ ::rtl::OUString m_aModuleIdentifier;
+- Menu* m_pVCLMenu;
++ AbstractMenu* m_pVCLMenu;
+ ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > m_xFrame;
+ ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > m_xUICommandLabels;
+ ::com::sun::star::uno::Reference< ::com::sun::star::frame::XUIControllerRegistration > m_xPopupMenuControllerRegistration;
+diff --git a/framework/inc/uielement/menubarmerger.hxx b/framework/inc/uielement/menubarmerger.hxx
+index 869e031..17a2b3f 100644
+--- a/framework/inc/uielement/menubarmerger.hxx
++++ b/framework/inc/uielement/menubarmerger.hxx
+@@ -60,7 +60,7 @@ enum RPResultInfo
+
+ struct ReferencePathInfo
+ {
+- Menu* pPopupMenu;
++ AbstractMenu* pPopupMenu;
+ sal_uInt16 nPos;
+ sal_Int32 nLevel;
+ RPResultInfo eResult;
+@@ -73,14 +73,14 @@ class MenuBarMerger
+
+ static void RetrieveReferencePath( const ::rtl::OUString&,
+ std::vector< ::rtl::OUString >& aReferencePath );
+- static ReferencePathInfo FindReferencePath( const std::vector< ::rtl::OUString >& aReferencePath, Menu* pMenu );
++ static ReferencePathInfo FindReferencePath( const std::vector< ::rtl::OUString >& aReferencePath, AbstractMenu* pMenu );
+ static sal_uInt16 FindMenuItem( const ::rtl::OUString& rCmd,
+- Menu* pMenu );
++ AbstractMenu* pMenu );
+ static void GetMenuEntry( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rAddonMenuEntry,
+ AddonMenuItem& aAddonMenu );
+ static void GetSubMenu( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > >& rSubMenuEntries,
+ AddonMenuContainer& rSubMenu );
+- static bool ProcessMergeOperation( Menu* pMenu,
++ static bool ProcessMergeOperation( AbstractMenu* pMenu,
+ sal_uInt16 nPos,
+ sal_uInt16& rItemId,
+ const ::rtl::OUString& rMergeCommand,
+@@ -95,21 +95,21 @@ class MenuBarMerger
+ const ::rtl::OUString& rModuleIdentifier,
+ const AddonMenuContainer& rAddonMenuItems );
+ static bool ProcessFallbackOperation();
+- static bool MergeMenuItems( Menu* pMenu,
++ static bool MergeMenuItems( AbstractMenu* pMenu,
+ sal_uInt16 nPos,
+ sal_uInt16 nModIndex,
+ sal_uInt16& rItemId,
+ const ::rtl::OUString& rModuleIdentifier,
+ const AddonMenuContainer& rAddonMenuItems );
+- static bool ReplaceMenuItem( Menu* pMenu,
++ static bool ReplaceMenuItem( AbstractMenu* pMenu,
+ sal_uInt16 nPos,
+ sal_uInt16& rItemId,
+ const ::rtl::OUString& rModuleIdentifier,
+ const AddonMenuContainer& rAddonMenuItems );
+- static bool RemoveMenuItems( Menu* pMenu,
++ static bool RemoveMenuItems( AbstractMenu* pMenu,
+ sal_uInt16 nPos,
+ const ::rtl::OUString& rMergeCommandParameter );
+- static bool CreateSubMenu( Menu* pSubMenu,
++ static bool CreateSubMenu( AbstractMenu* pSubMenu,
+ sal_uInt16& nItemId,
+ const ::rtl::OUString& rModuleIdentifier,
+ const AddonMenuContainer& rAddonSubMenu );
+diff --git a/framework/inc/uielement/menubarwrapper.hxx b/framework/inc/uielement/menubarwrapper.hxx
+index 7aa5c0a..3ef24f0 100644
+--- a/framework/inc/uielement/menubarwrapper.hxx
++++ b/framework/inc/uielement/menubarwrapper.hxx
+@@ -96,6 +96,7 @@ class MenuBarWrapper : public UIConfigElementWrapperBase,
+ private:
+ virtual void impl_fillNewData();
+ void fillPopupControllerCache();
++// void GenerateFullMenuBar( MenuBar *pMenuBar );
+
+ sal_Bool m_bRefreshPopupControllerCache : 1;
+ com::sun::star::uno::Reference< com::sun::star::lang::XComponent > m_xMenuBarManager;
+diff --git a/framework/source/classes/menumanager.cxx b/framework/source/classes/menumanager.cxx
+index 8319bec..bf9a1e4 100644
+--- a/framework/source/classes/menumanager.cxx
++++ b/framework/source/classes/menumanager.cxx
+@@ -134,7 +134,7 @@ const char UNO_COMMAND[] = ".uno:";
+
+ MenuManager::MenuManager(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory,
+- REFERENCE< XFRAME >& rFrame, Menu* pMenu, sal_Bool bDelete, sal_Bool bDeleteChildren )
++ REFERENCE< XFRAME >& rFrame, AbstractMenu* pMenu, sal_Bool bDelete, sal_Bool bDeleteChildren )
+ :
+ ThreadHelpBase( &Application::GetSolarMutex() ),
+ mxServiceFactory(xServiceFactory)
+@@ -479,7 +479,7 @@ void SAL_CALL MenuManager::disposing( const EVENTOBJECT& Source ) throw ( RUNTIM
+ }
+
+
+-void MenuManager::UpdateSpecialFileMenu( Menu* pMenu )
++void MenuManager::UpdateSpecialFileMenu( AbstractMenu* pMenu )
+ {
+ // update picklist
+ Sequence< Sequence< PropertyValue > > aHistoryList = SvtHistoryOptions().GetList( ePICKLIST );
+@@ -645,7 +645,7 @@ void MenuManager::UpdateSpecialFileMenu( Menu* pMenu )
+ }
+ }
+
+-void MenuManager::UpdateSpecialWindowMenu( Menu* pMenu,const Reference< XMultiServiceFactory >& xServiceFactory,framework::IMutex& _rMutex )
++void MenuManager::UpdateSpecialWindowMenu( AbstractMenu* pMenu,const Reference< XMultiServiceFactory >& xServiceFactory,framework::IMutex& _rMutex )
+ {
+ // update window list
+ ::std::vector< ::rtl::OUString > aNewWindowListVector;
+@@ -759,7 +759,7 @@ void MenuManager::CreatePicklistArguments( Sequence< PropertyValue >& aArgsList,
+ // vcl handler
+ //_________________________________________________________________________________________________________________
+
+-IMPL_LINK( MenuManager, Activate, Menu *, pMenu )
++IMPL_LINK( MenuManager, Activate, AbstractMenu *, pMenu )
+ {
+ if ( pMenu == m_pVCLMenu )
+ {
+@@ -862,7 +862,7 @@ IMPL_LINK( MenuManager, Activate, Menu *, pMenu )
+ }
+
+
+-IMPL_LINK( MenuManager, Deactivate, Menu *, pMenu )
++IMPL_LINK( MenuManager, Deactivate, AbstractMenu *, pMenu )
+ {
+ if ( pMenu == m_pVCLMenu )
+ m_bActive = sal_False;
+@@ -871,7 +871,7 @@ IMPL_LINK( MenuManager, Deactivate, Menu *, pMenu )
+ }
+
+
+-IMPL_LINK( MenuManager, Select, Menu *, pMenu )
++IMPL_LINK( MenuManager, Select, AbstractMenu *, pMenu )
+ {
+ URL aTargetURL;
+ Sequence<PropertyValue> aArgs;
+@@ -973,7 +973,7 @@ void MenuManager::AddMenu(PopupMenu* _pPopupMenu,const ::rtl::OUString& _sItemCo
+ m_aMenuItemHandlerVector.push_back( pMenuItemHandler );
+ }
+
+-sal_uInt16 MenuManager::FillItemCommand(::rtl::OUString& _rItemCommand,Menu* _pMenu,sal_uInt16 _nIndex) const
++sal_uInt16 MenuManager::FillItemCommand(::rtl::OUString& _rItemCommand, AbstractMenu* _pMenu,sal_uInt16 _nIndex) const
+ {
+ sal_uInt16 nItemId = _pMenu->GetItemId( _nIndex );
+
+@@ -987,7 +987,7 @@ sal_uInt16 MenuManager::FillItemCommand(::rtl::OUString& _rItemCommand,Menu* _pM
+ }
+ return nItemId;
+ }
+-void MenuManager::FillMenuImages(Reference< XFrame >& _xFrame,Menu* _pMenu,sal_Bool bShowMenuImages)
++void MenuManager::FillMenuImages(Reference< XFrame >& _xFrame, AbstractMenu* _pMenu,sal_Bool bShowMenuImages)
+ {
+ AddonsOptions aAddonOptions;
+
+diff --git a/framework/source/uielement/menubarmanager.cxx b/framework/source/uielement/menubarmanager.cxx
+index 4c64446..6f19829 100644
+--- a/framework/source/uielement/menubarmanager.cxx
++++ b/framework/source/uielement/menubarmanager.cxx
+@@ -196,7 +196,7 @@ MenuBarManager::MenuBarManager(
+ const Reference< XURLTransformer >& _xURLTransformer,
+ const Reference< XDispatchProvider >& rDispatchProvider,
+ const rtl::OUString& rModuleIdentifier,
+- Menu* pMenu, sal_Bool bDelete, sal_Bool bDeleteChildren )
++ AbstractMenu* pMenu, sal_Bool bDelete, sal_Bool bDeleteChildren )
+ : ThreadHelpBase( &Application::GetSolarMutex() ), OWeakObject()
+ , m_bDisposed( sal_False )
+ , m_bRetrieveImages( sal_False )
+@@ -771,7 +771,7 @@ void SAL_CALL MenuBarManager::disposing( const EventObject& Source ) throw ( Run
+ }
+
+
+-void MenuBarManager::CheckAndAddMenuExtension( Menu* pMenu )
++void MenuBarManager::CheckAndAddMenuExtension( AbstractMenu* pMenu )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::CheckAndAddMenuExtension" );
+ static const char REFERENCECOMMAND_BEFORE[] = ".uno:About";
+@@ -803,7 +803,7 @@ void MenuBarManager::CheckAndAddMenuExtension( Menu* pMenu )
+ }
+ }
+
+-static void lcl_CheckForChildren(Menu* pMenu, sal_uInt16 nItemId)
++static void lcl_CheckForChildren(AbstractMenu* pMenu, sal_uInt16 nItemId)
+ {
+ if (PopupMenu* pThisPopup = pMenu->GetPopupMenu( nItemId ))
+ pMenu->EnableItem( nItemId, pThisPopup->GetItemCount() ? true : false );
+@@ -813,7 +813,7 @@ static void lcl_CheckForChildren(Menu* pMenu, sal_uInt16 nItemId)
+ // vcl handler
+ //_________________________________________________________________________________________________________________
+
+-IMPL_LINK( MenuBarManager, Activate, Menu *, pMenu )
++IMPL_LINK( MenuBarManager, Activate, AbstractMenu *, pMenu )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::Activate" );
+ if ( pMenu == m_pVCLMenu )
+@@ -863,8 +863,9 @@ IMPL_LINK( MenuBarManager, Activate, Menu *, pMenu )
+ ( pMenu->GetItemText( nItemId ).Len() == 0 ))
+ {
+ String aCommand = pMenu->GetItemCommand( nItemId );
+- if ( aCommand.Len() > 0 )
++ if ( aCommand.Len() > 0 ) {
+ pMenu->SetItemText( nItemId, RetrieveLabelFromCommand( aCommand ));
++ }
+ }
+ }
+
+@@ -1004,11 +1005,14 @@ IMPL_LINK( MenuBarManager, Activate, Menu *, pMenu )
+ }
+ }
+
++ // Freeze the menu
++// m_pVCLMenu->Freeze();
++
+ return 1;
+ }
+
+
+-IMPL_LINK( MenuBarManager, Deactivate, Menu *, pMenu )
++IMPL_LINK( MenuBarManager, Deactivate, AbstractMenu *, pMenu )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::Deactivate" );
+ if ( pMenu == m_pVCLMenu )
+@@ -1044,7 +1048,7 @@ IMPL_LINK( MenuBarManager, AsyncSettingsHdl, Timer*,)
+ return 0;
+ }
+
+-IMPL_LINK( MenuBarManager, Select, Menu *, pMenu )
++IMPL_LINK( MenuBarManager, Select, AbstractMenu *, pMenu )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::Select" );
+ URL aTargetURL;
+@@ -1219,7 +1223,7 @@ sal_Bool MenuBarManager::CreatePopupMenuController( MenuItemHandler* pMenuItemHa
+ return sal_False;
+ }
+
+-void MenuBarManager::FillMenuManager( Menu* pMenu, const Reference< XFrame >& rFrame, const Reference< XDispatchProvider >& rDispatchProvider, const rtl::OUString& rModuleIdentifier, sal_Bool bDelete, sal_Bool bDeleteChildren )
++void MenuBarManager::FillMenuManager( AbstractMenu* pMenu, const Reference< XFrame >& rFrame, const Reference< XDispatchProvider >& rDispatchProvider, const rtl::OUString& rModuleIdentifier, sal_Bool bDelete, sal_Bool bDeleteChildren )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::FillMenuManager" );
+ m_xFrame = rFrame;
+@@ -1664,8 +1668,8 @@ void MenuBarManager::RetrieveImageManagers()
+ }
+
+ void MenuBarManager::FillMenuWithConfiguration(
+- sal_uInt16& nId,
+- Menu* pMenu,
++ sal_uInt16& nId,
++ AbstractMenu* pMenu,
+ const ::rtl::OUString& rModuleIdentifier,
+ const Reference< XIndexAccess >& rItemContainer,
+ const Reference< XURLTransformer >& rTransformer )
+@@ -1675,7 +1679,7 @@ void MenuBarManager::FillMenuWithConfiguration(
+ MenuBarManager::FillMenu( nId, pMenu, rModuleIdentifier, rItemContainer, xEmptyDispatchProvider );
+
+ // Merge add-on menu entries into the menu bar
+- MenuBarManager::MergeAddonMenus( static_cast< Menu* >( pMenu ),
++ MenuBarManager::MergeAddonMenus( static_cast< AbstractMenu* >( pMenu ),
+ AddonsOptions().GetMergeMenuInstructions(),
+ rModuleIdentifier );
+
+@@ -1700,15 +1704,15 @@ void MenuBarManager::FillMenuWithConfiguration(
+ }
+
+ void MenuBarManager::FillMenu(
+- sal_uInt16& nId,
+- Menu* pMenu,
++ sal_uInt16& nId,
++ AbstractMenu* pMenu,
+ const rtl::OUString& rModuleIdentifier,
+ const Reference< XIndexAccess >& rItemContainer,
+ const Reference< XDispatchProvider >& rDispatchProvider )
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::FillMenu" );
+ // Fill menu bar with container contents
+- for ( sal_Int32 n = 0; n < rItemContainer->getCount(); n++ )
++ for ( sal_Int32 n = 0; n < rItemContainer->getCount(); n++ )
+ {
+ Sequence< PropertyValue > aProp;
+ rtl::OUString aCommandURL;
+@@ -1811,7 +1815,7 @@ void MenuBarManager::FillMenu(
+ }
+
+ void MenuBarManager::MergeAddonMenus(
+- Menu* pMenuBar,
++ AbstractMenu* pMenuBar,
+ const MergeMenuInstructionContainer& aMergeInstructionContainer,
+ const ::rtl::OUString& rModuleIdentifier )
+ {
+@@ -1836,7 +1840,7 @@ void MenuBarManager::MergeAddonMenus(
+ MenuBarMerger::GetSubMenu( rMergeInstruction.aMergeMenu, aMergeMenuItems );
+
+ // try to find the reference point for our merge operation
+- Menu* pMenu = pMenuBar;
++ AbstractMenu* pMenu = pMenuBar;
+ ReferencePathInfo aResult = MenuBarMerger::FindReferencePath( aMergePath, pMenu );
+
+ if ( aResult.eResult == RP_OK )
+@@ -1916,7 +1920,7 @@ void MenuBarManager::SetItemContainer( const Reference< XIndexAccess >& rItemCon
+ sal_uInt16 nId = 1;
+
+ // Fill menu bar with container contents
+- FillMenuWithConfiguration( nId, (Menu *)m_pVCLMenu, m_aModuleIdentifier, rItemContainer, m_xURLTransformer );
++ FillMenuWithConfiguration( nId, (AbstractMenu *)m_pVCLMenu, m_aModuleIdentifier, rItemContainer, m_xURLTransformer );
+
+ // Refill menu manager again
+ Reference< XDispatchProvider > xDispatchProvider;
+@@ -1996,7 +2000,7 @@ void MenuBarManager::AddMenu(MenuBarManager* pSubMenuManager,const ::rtl::OUStri
+ m_aMenuItemHandlerVector.push_back( pMenuItemHandler );
+ }
+
+-sal_uInt16 MenuBarManager::FillItemCommand(::rtl::OUString& _rItemCommand,Menu* _pMenu,sal_uInt16 _nIndex) const
++sal_uInt16 MenuBarManager::FillItemCommand(::rtl::OUString& _rItemCommand, AbstractMenu* _pMenu,sal_uInt16 _nIndex) const
+ {
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "MenuBarManager::FillItemCommand" );
+ sal_uInt16 nItemId = _pMenu->GetItemId( _nIndex );
+diff --git a/framework/source/uielement/menubarmerger.cxx b/framework/source/uielement/menubarmerger.cxx
+index 544c52a..213ad89 100644
+--- a/framework/source/uielement/menubarmerger.cxx
++++ b/framework/source/uielement/menubarmerger.cxx
+@@ -96,7 +96,7 @@ void MenuBarMerger::RetrieveReferencePath(
+
+ ReferencePathInfo MenuBarMerger::FindReferencePath(
+ const ::std::vector< ::rtl::OUString >& rReferencePath,
+- Menu* pMenu )
++ AbstractMenu* pMenu )
+ {
+ sal_uInt32 i( 0 );
+ const sal_uInt32 nCount( rReferencePath.size() );
+@@ -108,7 +108,7 @@ ReferencePathInfo MenuBarMerger::FindReferencePath(
+ return aResult;
+ }
+
+- Menu* pCurrMenu( pMenu );
++ AbstractMenu* pCurrMenu( pMenu );
+ RPResultInfo eResult( RP_OK );
+
+ sal_Int32 nLevel( - 1 );
+@@ -157,7 +157,7 @@ ReferencePathInfo MenuBarMerger::FindReferencePath(
+ return aResult;
+ }
+
+-sal_uInt16 MenuBarMerger::FindMenuItem( const ::rtl::OUString& rCmd, Menu* pCurrMenu )
++sal_uInt16 MenuBarMerger::FindMenuItem( const ::rtl::OUString& rCmd, AbstractMenu* pCurrMenu )
+ {
+ for ( sal_uInt16 i = 0; i < pCurrMenu->GetItemCount(); i++ )
+ {
+@@ -173,7 +173,7 @@ sal_uInt16 MenuBarMerger::FindMenuItem( const ::rtl::OUString& rCmd, Menu* pCurr
+ }
+
+ bool MenuBarMerger::CreateSubMenu(
+- Menu* pSubMenu,
++ AbstractMenu* pSubMenu,
+ sal_uInt16& nItemId,
+ const ::rtl::OUString& rModuleIdentifier,
+ const AddonMenuContainer& rAddonSubMenu )
+@@ -211,7 +211,7 @@ bool MenuBarMerger::CreateSubMenu(
+ }
+
+ bool MenuBarMerger::MergeMenuItems(
+- Menu* pMenu,
++ AbstractMenu* pMenu,
+ sal_uInt16 nPos,
+ sal_uInt16 nModIndex,
+ sal_uInt16& nItemId,
+@@ -253,7 +253,7 @@ bool MenuBarMerger::MergeMenuItems(
+ }
+
+ bool MenuBarMerger::ReplaceMenuItem(
+- Menu* pMenu,
++ AbstractMenu* pMenu,
+ sal_uInt16 nPos,
+ sal_uInt16& rItemId,
+ const ::rtl::OUString& rModuleIdentifier,
+@@ -267,7 +267,7 @@ bool MenuBarMerger::ReplaceMenuItem(
+ }
+
+ bool MenuBarMerger::RemoveMenuItems(
+- Menu* pMenu,
++ AbstractMenu* pMenu,
+ sal_uInt16 nPos,
+ const ::rtl::OUString& rMergeCommandParameter )
+ {
+@@ -287,7 +287,7 @@ bool MenuBarMerger::RemoveMenuItems(
+ }
+
+ bool MenuBarMerger::ProcessMergeOperation(
+- Menu* pMenu,
++ AbstractMenu* pMenu,
+ sal_uInt16 nPos,
+ sal_uInt16& nItemId,
+ const ::rtl::OUString& rMergeCommand,
+@@ -336,7 +336,7 @@ bool MenuBarMerger::ProcessFallbackOperation(
+ }
+ else if ( rMergeFallback.equalsAsciiL( MERGEFALLBACK_ADDPATH, MERGEFALLBACK_ADDPATH_LEN ))
+ {
+- Menu* pCurrMenu( aRefPathInfo.pPopupMenu );
++ AbstractMenu* pCurrMenu( aRefPathInfo.pPopupMenu );
+ sal_Int32 nLevel( aRefPathInfo.nLevel );
+ const sal_Int32 nSize( rReferencePath.size() );
+ bool bFirstLevel( true );
+diff --git a/framework/source/uielement/menubarwrapper.cxx b/framework/source/uielement/menubarwrapper.cxx
+index 45d5bf8..f819b5a 100644
+--- a/framework/source/uielement/menubarwrapper.cxx
++++ b/framework/source/uielement/menubarwrapper.cxx
+@@ -130,6 +130,19 @@ void SAL_CALL MenuBarWrapper::dispose() throw (::com::sun::star::uno::RuntimeExc
+ m_bDisposed = sal_True;
+ }
+
++//void generateFullMenuBar( MenuBarManager *pMenuBarManager, MenuBar *pMenuBar )
++//{
++// for (int i=0; i < pMenuBar->GetItemCount(); i++)
++// {
++// sal_Int16 nId = pMenuBar->GetItemId( i );
++
++// String aCommandLabel = pMenuBar->GetItemCommand( nId );
++
++// String label = pMenuBarManager->RetrieveLabelFromCommand( aCommandLabel );
++// pMenuBar->SetItemText( nId, label );
++// }
++//}
++
+ // XInitialization
+ void SAL_CALL MenuBarWrapper::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException )
+ {
+@@ -216,6 +229,9 @@ void SAL_CALL MenuBarWrapper::initialize( const Sequence< Any >& aArguments ) th
+ sal_True );
+
+ m_xMenuBarManager = Reference< XComponent >( static_cast< OWeakObject *>( pMenuBarManager ), UNO_QUERY );
++
++// pMenuBarManager->GenerateFullMenuHierarchy( pVCLMenuBar );
++ pVCLMenuBar->Freeze();
+ }
+
+ // Initialize toolkit menu bar implementation to have awt::XMenuBar for data exchange.
+diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
+index 53f9d4a..56d2bf3 100644
+--- a/vcl/Library_vcl.mk
++++ b/vcl/Library_vcl.mk
+@@ -95,6 +95,7 @@ $(eval $(call gb_Library_use_externals,vcl,\
+ icule \
+ icuuc \
+ lcms2 \
++ gio \
+ ))
+
+ $(eval $(call gb_Library_add_cobjects,vcl,\
+diff --git a/vcl/Library_vclplug_gtk.mk b/vcl/Library_vclplug_gtk.mk
+index e816fcf..c4cce2a 100644
+--- a/vcl/Library_vclplug_gtk.mk
++++ b/vcl/Library_vclplug_gtk.mk
+@@ -99,10 +99,13 @@ $(eval $(call gb_Library_add_exception_objects,vclplug_gtk,\
+ vcl/unx/gtk/gdi/salnativewidgets-gtk \
+ vcl/unx/gtk/window/gtkframe \
+ vcl/unx/gtk/window/gtkobject \
+- vcl/unx/gtk/fpicker/resourceprovider \
+- vcl/unx/gtk/fpicker/SalGtkPicker \
+- vcl/unx/gtk/fpicker/SalGtkFilePicker \
+- vcl/unx/gtk/fpicker/SalGtkFolderPicker \
++ vcl/unx/gtk/window/gloactiongroup \
++ vcl/unx/gtk/window/gtksalmenu \
++ vcl/unx/gtk/window/glomenu \
++ vcl/unx/gtk/fpicker/resourceprovider \
++ vcl/unx/gtk/fpicker/SalGtkPicker \
++ vcl/unx/gtk/fpicker/SalGtkFilePicker \
++ vcl/unx/gtk/fpicker/SalGtkFolderPicker \
+ ))
+
+ ifeq ($(ENABLE_GTK_PRINT),TRUE)
+diff --git a/vcl/Library_vclplug_gtk3.mk b/vcl/Library_vclplug_gtk3.mk
+index 120199c..fd66689 100644
+--- a/vcl/Library_vclplug_gtk3.mk
++++ b/vcl/Library_vclplug_gtk3.mk
+@@ -110,6 +110,9 @@ $(eval $(call gb_Library_add_exception_objects,vclplug_gtk3,\
+ vcl/unx/gtk3/gdi/gtk3salprn-gtk \
+ vcl/unx/gtk3/window/gtk3gtkframe \
+ vcl/unx/gtk3/window/gtk3gtkobject \
++ vcl/unx/gtk3/window/gtk3gtksalmenu \
++ vcl/unx/gtk3/window/gtk3glomenu \
++ vcl/unx/gtk3/window/gtk3gloactiongroup \
+ ))
+
+ $(eval $(call gb_Library_use_static_libraries,vclplug_gtk3,\
+diff --git a/vcl/inc/salmenu.hxx b/vcl/inc/salmenu.hxx
+index 1d14a7e..2f8d680 100644
+--- a/vcl/inc/salmenu.hxx
++++ b/vcl/inc/salmenu.hxx
+@@ -41,7 +41,7 @@ class SalFrame;
+
+ struct SalItemParams
+ {
+- sal_uInt16 nId; // item Id
++ sal_uInt16 nId; // item Id
+ MenuItemType eType; // MenuItem-Type
+ MenuItemBits nBits; // MenuItem-Bits
+ Menu* pMenu; // Pointer to Menu
+@@ -52,7 +52,7 @@ struct SalItemParams
+
+ struct SalMenuButtonItem
+ {
+- sal_uInt16 mnId;
++ sal_uInt16 mnId;
+ Image maImage;
+ rtl::OUString maToolTipText;
+
+@@ -91,6 +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 ) {}
++ virtual void Freeze() {}
++
+ // return an empty rectangle if not implemented
+ // return Rectangle( Point( -1, -1 ), Size( 1, 1 ) ) if menu bar buttons implemented
+ // but rectangle cannot be determined
+diff --git a/vcl/inc/unx/gtk/gloactiongroup.h b/vcl/inc/unx/gtk/gloactiongroup.h
+new file mode 100644
+index 0000000..852a40f
+--- /dev/null
++++ b/vcl/inc/unx/gtk/gloactiongroup.h
+@@ -0,0 +1,63 @@
++#ifndef GLOACTIONGROUP_H
++#define GLOACTIONGROUP_H
++
++#include <gio/gio.h>
++
++G_BEGIN_DECLS
++
++#define G_TYPE_LO_ACTION_GROUP (g_lo_action_group_get_type ())
++#define G_LO_ACTION_GROUP(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
++ G_TYPE_LO_ACTION_GROUP, GLOActionGroup))
++#define G_LO_ACTION_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \
++ G_TYPE_LO_ACTION_GROUP, GLOActionGroupClass))
++#define G_IS_LO_ACTION_GROUP(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \
++ G_TYPE_LO_ACTION_GROUP))
++#define G_IS_LO_ACTION_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \
++ G_TYPE_LO_ACTION_GROUP))
++#define G_LO_ACTION_GROUP_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), \
++ G_TYPE_LO_ACTION_GROUP, GLOActionGroupClass))
++
++typedef struct _GLOActionGroupPrivate GLOActionGroupPrivate;
++typedef struct _GLOActionGroupClass GLOActionGroupClass;
++typedef struct _GLOActionGroup GLOActionGroup;
++
++struct _GLOActionGroup
++{
++ /*< private >*/
++ GObject parent_instance;
++
++ GLOActionGroupPrivate *priv;
++};
++
++struct _GLOActionGroupClass
++{
++ /*< private >*/
++ GObjectClass parent_class;
++
++ /*< private >*/
++ gpointer padding[12];
++};
++
++GType g_lo_action_group_get_type (void) G_GNUC_CONST;
++
++GLOActionGroup * g_lo_action_group_new (void);
++
++void g_lo_action_group_insert (GLOActionGroup *group,
++ const gchar *action_name,
++ gpointer action_info);
++
++void g_lo_action_group_set_action_enabled (GLOActionGroup *group,
++ const gchar *action_name,
++ gboolean enabled);
++
++void g_lo_action_group_remove (GLOActionGroup *group,
++ const gchar *action_name);
++
++void g_lo_action_group_clear (GLOActionGroup *group);
++
++void g_lo_action_group_merge (GLOActionGroup *input_group,
++ GLOActionGroup *output_group);
++
++G_END_DECLS
++
++#endif // GLOACTIONGROUP_H
+diff --git a/vcl/inc/unx/gtk/glomenu.h b/vcl/inc/unx/gtk/glomenu.h
+new file mode 100644
+index 0000000..db2f034
+--- /dev/null
++++ b/vcl/inc/unx/gtk/glomenu.h
+@@ -0,0 +1,134 @@
++/*
++ * Copyright © 2011 Canonical Ltd.
++ *
++ * This library is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License as
++ * published by the Free Software Foundation; either version 2 of the
++ * licence, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++ * USA.
++ *
++ * Author: Ryan Lortie <desrt@desrt.ca>
++ */
++
++#ifndef __G_LO_MENU_H__
++#define __G_LO_MENU_H__
++
++#include <gio/gio.h>
++
++G_BEGIN_DECLS
++
++#define G_TYPE_LO_MENU (g_lo_menu_get_type ())
++#define G_LO_MENU(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
++ G_TYPE_LO_MENU, GLOMenu))
++#define G_IS_LO_MENU(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \
++ G_TYPE_LO_MENU))
++
++#define G_TYPE_LO_MENU_ITEM (g_lo_menu_item_get_type ())
++#define G_LO_MENU_ITEM(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
++ G_TYPE_LO_MENU_ITEM, GLOMenuItem))
++#define G_IS_LO_MENU_ITEM(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \
++ G_TYPE_LO_MENU_ITEM))
++
++typedef struct _GLOMenuItem GLOMenuItem;
++typedef struct _GLOMenu GLOMenu;
++
++GLIB_AVAILABLE_IN_2_32
++GType g_lo_menu_get_type (void) G_GNUC_CONST;
++GLIB_AVAILABLE_IN_2_32
++GLOMenu * g_lo_menu_new (void);
++
++void g_lo_menu_freeze (GLOMenu *menu);
++
++void g_lo_menu_insert_item (GLOMenu *menu,
++ gint position,
++ GLOMenuItem *item);
++void g_lo_menu_prepend_item (GLOMenu *menu,
++ GLOMenuItem *item);
++void g_lo_menu_append_item (GLOMenu *menu,
++ GLOMenuItem *item);
++void g_lo_menu_remove (GLOMenu *menu,
++ gint position);
++
++void g_lo_menu_insert (GLOMenu *menu,
++ gint position,
++ const gchar *label,
++ const gchar *detailed_action);
++void g_lo_menu_prepend (GLOMenu *menu,
++ const gchar *label,
++ const gchar *detailed_action);
++void g_lo_menu_append (GLOMenu *menu,
++ const gchar *label,
++ const gchar *detailed_action);
++
++void g_lo_menu_insert_section (GLOMenu *menu,
++ gint position,
++ const gchar *label,
++ GMenuModel *section);
++void g_lo_menu_prepend_section (GLOMenu *menu,
++ const gchar *label,
++ GMenuModel *section);
++void g_lo_menu_append_section (GLOMenu *menu,
++ const gchar *label,
++ GMenuModel *section);
++
++void g_lo_menu_insert_submenu (GLOMenu *menu,
++ gint position,
++ const gchar *label,
++ GMenuModel *submenu);
++void g_lo_menu_prepend_submenu (GLOMenu *menu,
++ const gchar *label,
++ GMenuModel *submenu);
++void g_lo_menu_append_submenu (GLOMenu *menu,
++ const gchar *label,
++ GMenuModel *submenu);
++
++
++GType g_lo_menu_item_get_type (void) G_GNUC_CONST;
++GLOMenuItem * g_lo_menu_item_new (const gchar *label,
++ const gchar *detailed_action);
++
++GLOMenuItem * g_lo_menu_item_new_submenu (const gchar *label,
++ GMenuModel *submenu);
++
++GLOMenuItem * g_lo_menu_item_new_section (const gchar *label,
++ GMenuModel *section);
++
++void g_lo_menu_item_set_attribute_value (GLOMenuItem *menu_item,
++ const gchar *attribute,
++ GVariant *value);
++void g_lo_menu_item_set_attribute (GLOMenuItem *menu_item,
++ const gchar *attribute,
++ const gchar *format_string,
++ ...);
++void g_lo_menu_item_set_link (GLOMenuItem *menu_item,
++ const gchar *link,
++ GMenuModel *model);
++void g_lo_menu_item_set_label (GLOMenuItem *menu_item,
++ const gchar *label);
++void g_lo_menu_item_set_submenu (GLOMenuItem *menu_item,
++ GMenuModel *submenu);
++void g_lo_menu_item_set_section (GLOMenuItem *menu_item,
++ GMenuModel *section);
++void g_lo_menu_item_set_action_and_target_value (GLOMenuItem *menu_item,
++ const gchar *action,
++ GVariant *target_value);
++void g_lo_menu_item_set_action_and_target (GLOMenuItem *menu_item,
++ const gchar *action,
++ const gchar *format_string,
++ ...);
++void g_lo_menu_item_set_detailed_action (GLOMenuItem *menu_item,
++ const gchar *detailed_action);
++
++G_END_DECLS
++
++#endif /* __G_LO_MENU_H__ */
++
+diff --git a/vcl/inc/unx/gtk/gtkinst.hxx b/vcl/inc/unx/gtk/gtkinst.hxx
+index 89743ca..5ec226e 100644
+--- a/vcl/inc/unx/gtk/gtkinst.hxx
++++ b/vcl/inc/unx/gtk/gtkinst.hxx
+@@ -113,6 +113,10 @@ public:
+ virtual SalSystem* CreateSalSystem();
+ virtual SalInfoPrinter* CreateInfoPrinter(SalPrinterQueueInfo* pPrinterQueueInfo, ImplJobSetup* pJobSetup);
+ virtual SalPrinter* CreatePrinter( SalInfoPrinter* pInfoPrinter );
++ virtual SalMenu* CreateMenu( sal_Bool, Menu* );
++ virtual void DestroyMenu( SalMenu* pMenu );
++ virtual SalMenuItem* CreateMenuItem( const SalItemParams* );
++ virtual void DestroyMenuItem( SalMenuItem* pItem );
+ virtual SalTimer* CreateSalTimer();
+ virtual void AddToRecentDocumentList(const rtl::OUString& rFileUrl, const rtl::OUString& rMimeType);
+ virtual SalVirtualDevice* CreateVirtualDevice( SalGraphics*,
+diff --git a/vcl/inc/unx/gtk/gtksalmenu.hxx b/vcl/inc/unx/gtk/gtksalmenu.hxx
+new file mode 100644
+index 0000000..c57d39d
+--- /dev/null
++++ b/vcl/inc/unx/gtk/gtksalmenu.hxx
+@@ -0,0 +1,123 @@
++/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
++/*************************************************************************
++ *
++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
++ *
++ * Copyright 2000, 2010 Oracle and/or its affiliates.
++ *
++ * OpenOffice.org - a multi-platform office productivity suite
++ *
++ * This file is part of OpenOffice.org.
++ *
++ * OpenOffice.org is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License version 3
++ * only, as published by the Free Software Foundation.
++ *
++ * OpenOffice.org is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU Lesser General Public License version 3 for more details
++ * (a copy is included in the LICENSE file that accompanied this code).
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * version 3 along with OpenOffice.org. If not, see
++ * <http://www.openoffice.org/license.html>
++ * for a copy of the LGPLv3 License.
++ *
++ ************************************************************************/
++
++#ifndef GTKSALMENU_HXX
++#define GTKSALMENU_HXX
++
++#include <vcl/sv.h>
++#include <vcl/bitmap.hxx>
++#include <unx/gtk/gtkframe.hxx>
++#include <unx/salmenu.h>
++
++#include <gio/gio.h>
++
++#include "glomenu.h"
++#include "gloactiongroup.h"
++
++#include <vector>
++
++
++class GtkSalMenuItem;
++
++class GtkSalMenu : public SalMenu
++{
++private:
++ sal_Bool mbMenuBar;
++ Menu* mpVCLMenu;
++ GtkSalMenu* mpParentSalMenu;
++ const GtkSalFrame* mpFrame;
++
++ std::vector< GMenuModel* > maSections;
++ std::vector< GtkSalMenuItem* > maItems;
++
++ // DBus attributes
++ GDBusConnection* pSessionBus;
++ sal_Int32 mMenubarId;
++ sal_Int32 mActionGroupId;
++
++ // GMenuModel and GActionGroup attributes
++ GMenuModel* mpMenuModel;
++ GMenuModel* mpCurrentSection;
++ GActionGroup* mpActionGroup;
++
++ GtkSalMenuItem* GetSalMenuItem( sal_uInt16 nId );
++ sal_Int16 GetSectionNumber( GMenuModel* pSection );
++
++public:
++ GtkSalMenu( sal_Bool bMenuBar );
++ virtual ~GtkSalMenu();
++
++ virtual sal_Bool VisibleMenuBar(); // must return TRUE to actually DISPLAY native menu bars
++ // otherwise only menu messages are processed (eg, OLE on Windows)
++
++ virtual void InsertItem( SalMenuItem* pSalMenuItem, unsigned nPos );
++ virtual void RemoveItem( unsigned nPos );
++ virtual void SetSubMenu( SalMenuItem* pSalMenuItem, SalMenu* pSubMenu, unsigned nPos );
++ virtual void SetFrame( const SalFrame* pFrame );
++ virtual const GtkSalFrame* GetFrame() const;
++ virtual void CheckItem( unsigned nPos, sal_Bool bCheck );
++ virtual void EnableItem( unsigned nPos, sal_Bool bEnable );
++ 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 );
++ virtual void GetSystemMenuData( SystemMenuData* pData );
++ virtual void SetItemCommand( unsigned nPos, SalMenuItem* pSalMenuItem, const rtl::OUString& aCommandStr );
++ virtual void Freeze();
++
++ virtual void SetMenu( Menu* pMenu ) { mpVCLMenu = pMenu; }
++ virtual Menu* GetMenu() { return mpVCLMenu; }
++ virtual GtkSalMenu* GetParentSalMenu() { return mpParentSalMenu; }
++ virtual GMenuModel* GetMenuModel() { return mpMenuModel; }
++ virtual GMenuModel* GetCurrentSection() { return mpCurrentSection; }
++ virtual unsigned GetItemCount() { return maItems.size(); }
++ virtual GtkSalMenuItem* GetItemAtPos( unsigned nPos ) { return maItems[ nPos ]; }
++ virtual GActionGroup* GetActionGroup() { return mpActionGroup; }
++};
++
++class GtkSalMenuItem : public SalMenuItem
++{
++public:
++ GtkSalMenuItem( const SalItemParams* );
++ virtual ~GtkSalMenuItem();
++
++ sal_uInt16 mnId; // Item ID
++ MenuItemBits mnBits; // Item bits
++ sal_uInt16 mnPos; // Item position
++ gchar* maCommand; // Item command
++ 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)
++ GMenuModel* mpParentSection; // Section where this item is added.
++ GLOMenuItem* mpMenuItem; // The GMenuItem
++ GVariantType* mpStateType; // A GVariantType with item state type
++ GVariant* mpState; // A GVariant with current item state
++};
++
++#endif // GTKSALMENU_HXX
++
++/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
+diff --git a/vcl/inc/unx/salmenu.h b/vcl/inc/unx/salmenu.h
+index f693a33..f9a89f7 100644
+--- a/vcl/inc/unx/salmenu.h
++++ b/vcl/inc/unx/salmenu.h
+@@ -31,7 +31,7 @@
+
+ #include <vcl/sv.h>
+ #include <vcl/bitmap.hxx>
+-#include <vcl/salmenu.hxx>
++#include <salmenu.hxx>
+
+
+ class X11SalMenu : public SalMenu
+@@ -40,15 +40,15 @@ public:
+ X11SalMenu() {}
+ virtual ~X11SalMenu();
+
+- virtual BOOL VisibleMenuBar(); // must return TRUE to actually DISPLAY native menu bars
++ virtual sal_Bool VisibleMenuBar(); // must return TRUE to actually DISPLAY native menu bars
+ // otherwise only menu messages are processed (eg, OLE on Windows)
+
+ virtual void InsertItem( SalMenuItem* pSalMenuItem, unsigned nPos );
+ virtual void RemoveItem( unsigned nPos );
+ virtual void SetSubMenu( SalMenuItem* pSalMenuItem, SalMenu* pSubMenu, unsigned nPos );
+ virtual void SetFrame( const SalFrame* pFrame );
+- virtual void CheckItem( unsigned nPos, BOOL bCheck );
+- virtual void EnableItem( unsigned nPos, BOOL bEnable );
++ virtual void CheckItem( unsigned nPos, sal_Bool bCheck );
++ virtual void EnableItem( unsigned nPos, sal_Bool bEnable );
+ 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 );
+diff --git a/vcl/inc/vcl/menu.hxx b/vcl/inc/vcl/menu.hxx
+index c9388ee..7538faf 100644
+--- a/vcl/inc/vcl/menu.hxx
++++ b/vcl/inc/vcl/menu.hxx
+@@ -112,6 +112,96 @@ struct ImplMenuDelData
+ bool isDeleted() const { return mpMenu == 0; }
+ };
+
++// ----------------
++// - AbstractMenu -
++// ----------------
++
++class VCL_DLLPUBLIC AbstractMenu : public Resource
++{
++public:
++ virtual ~AbstractMenu() {}
++
++ virtual SAL_DLLPRIVATE Window* ImplGetWindow() const = 0;
++
++ virtual void InsertItem( sal_uInt16 nItemId, const XubString& rStr,
++ MenuItemBits nItemBits = 0,
++ sal_uInt16 nPos = MENU_APPEND ) = 0;
++ virtual void InsertItem( sal_uInt16 nItemId,
++ const XubString& rString, const Image& rImage,
++ MenuItemBits nItemBits = 0,
++ sal_uInt16 nPos = MENU_APPEND ) = 0;
++ virtual void InsertSeparator( sal_uInt16 nPos = MENU_APPEND ) = 0;
++ virtual void RemoveItem( sal_uInt16 nPos ) = 0;
++ virtual void CopyItem( const Menu& rMenu, sal_uInt16 nPos,
++ sal_uInt16 nNewPos = MENU_APPEND ) = 0;
++ virtual void Clear() = 0;
++
++ virtual void SetMenuFlags( sal_uInt16 nFlags ) = 0;
++ virtual sal_uInt16 GetMenuFlags() const = 0;
++
++ virtual sal_uInt16 GetItemCount() const = 0;
++ virtual sal_uInt16 GetItemId( sal_uInt16 nPos ) const = 0;
++ virtual sal_uInt16 GetItemPos( sal_uInt16 nItemId ) const = 0;
++ virtual MenuItemType GetItemType( sal_uInt16 nPos ) const = 0;
++ virtual sal_uInt16 GetCurItemId() const = 0;
++
++ virtual void SetItemBits( sal_uInt16 nItemId, MenuItemBits nBits ) = 0;
++ virtual MenuItemBits GetItemBits( sal_uInt16 nItemId ) const = 0;
++
++ virtual void SetUserValue( sal_uInt16 nItemId, sal_uLong nValue ) = 0;
++ virtual sal_uLong GetUserValue( sal_uInt16 nItemId ) const = 0;
++
++ virtual void SetPopupMenu( sal_uInt16 nItemId, PopupMenu* pMenu ) = 0;
++ virtual PopupMenu* GetPopupMenu( sal_uInt16 nItemId ) const = 0;
++
++ virtual void SetAccelKey( sal_uInt16 nItemId, const KeyCode& rKeyCode ) = 0;
++
++ virtual void CheckItem( sal_uInt16 nItemId, sal_Bool bCheck = sal_True ) = 0;
++ virtual sal_Bool IsItemChecked( sal_uInt16 nItemId ) const = 0;
++
++ virtual void EnableItem( sal_uInt16 nItemId, sal_Bool bEnable = sal_True ) = 0;
++ virtual sal_Bool IsItemEnabled( sal_uInt16 nItemId ) const = 0;
++
++ virtual void ShowItem( sal_uInt16 nItemId, sal_Bool bVisible = sal_True ) = 0;
++ virtual void HideItem( sal_uInt16 nItemId ) = 0;
++
++ virtual sal_Bool IsMenuBar() const = 0;
++
++ virtual void RemoveDisabledEntries( sal_Bool bCheckPopups = sal_True,
++ sal_Bool bRemoveEmptyPopups = sal_False ) = 0;
++
++ virtual void SetItemText( sal_uInt16 nItemId, const XubString& rStr ) = 0;
++ virtual XubString GetItemText( sal_uInt16 nItemId ) const = 0;
++
++ virtual void SetItemImage( sal_uInt16 nItemId, const Image& rImage ) = 0;
++ virtual Image GetItemImage( sal_uInt16 nItemId ) const = 0;
++
++ virtual void SetItemCommand( sal_uInt16 nItemId, const XubString& rCommand ) = 0;
++ virtual const XubString& GetItemCommand( sal_uInt16 nItemId ) const = 0;
++
++ virtual void SetTipHelpText( sal_uInt16 nItemId, const XubString& rString ) = 0;
++
++ virtual void SetHelpCommand( sal_uInt16 nItemId, const XubString& rString ) = 0;
++ virtual const XubString& GetHelpCommand( sal_uInt16 nItemId ) const = 0;
++
++ virtual void SetHelpId( sal_uInt16 nItemId, const rtl::OString& rHelpId ) = 0;
++ virtual rtl::OString GetHelpId( sal_uInt16 nItemId ) const = 0;
++
++ virtual void SetActivateHdl( const Link& rLink ) = 0;
++
++ virtual void SetDeactivateHdl( const Link& rLink ) = 0;
++
++ virtual void SetHighlightHdl( const Link& rLink ) = 0;
++
++ virtual void SetSelectHdl( const Link& rLink ) = 0;
++
++ // Returns the system's menu handle if native menus are supported
++ // pData must point to a SystemMenuData structure
++ virtual sal_Bool GetSystemMenuData( SystemMenuData* pData ) const = 0;
++
++ virtual void Freeze(void) = 0;
++};
++
+ // --------
+ // - Menu -
+ // --------
+@@ -123,7 +213,7 @@ struct MenuLogo
+ Color aEndColor;
+ };
+
+-class VCL_DLLPUBLIC Menu : public Resource
++class VCL_DLLPUBLIC Menu : public AbstractMenu
+ {
+ friend class MenuBar;
+ friend class MenuBarWindow;
+@@ -158,7 +248,7 @@ private:
+ sal_uInt16 nImgOrChkPos;
+ sal_uInt16 nTextPos;
+
+- sal_Bool bIsMenuBar : 1, // Handelt es sich um den MenuBar
++ sal_Bool bIsMenuBar : 1, // Handelt es sich um den MenuBar
+ bCanceled : 1, // Waehrend eines Callbacks abgebrochen
+ bInCallback : 1, // In Activate/Deactivate
+ bKilled : 1; // Gekillt...
+@@ -208,11 +298,13 @@ public:
+ Menu();
+ Menu( sal_Bool bMenuBar );
+ SAL_DLLPRIVATE Window* ImplGetWindow() const { return pWindow; }
+-#if defined(QUARTZ)
+- // ImplSelectWithStart() is used in vcl/aqua/source/window/salnsmenu.mm
+- SAL_DLLPRIVATE void ImplSelectWithStart( Menu* pStartMenu = NULL );
+-#endif
+-public:
++//#if defined(QUARTZ)
++// // ImplSelectWithStart() is used in vcl/aqua/source/window/salnsmenu.mm
++// SAL_DLLPRIVATE void ImplSelectWithStart( Menu* pStartMenu = NULL );
++//#endif
++ void ImplSelectWithStart( Menu* pStartMenu = NULL );
++
++ public:
+ virtual ~Menu();
+
+ virtual void Activate();
+@@ -276,12 +368,12 @@ public:
+ void ShowItem( sal_uInt16 nItemId, sal_Bool bVisible = sal_True );
+ void HideItem( sal_uInt16 nItemId ) { ShowItem( nItemId, sal_False ); }
+
+- sal_Bool IsItemPosVisible( sal_uInt16 nItemPos ) const;
+- sal_Bool IsMenuVisible() const;
+- sal_Bool IsMenuBar() const { return bIsMenuBar; }
++ sal_Bool IsItemPosVisible( sal_uInt16 nItemPos ) const;
++ sal_Bool IsMenuVisible() const;
++ sal_Bool IsMenuBar() const { return bIsMenuBar; }
+
+ void RemoveDisabledEntries( sal_Bool bCheckPopups = sal_True, sal_Bool bRemoveEmptyPopups = sal_False );
+- sal_Bool HasValidEntries( sal_Bool bCheckPopups = sal_True );
++ sal_Bool HasValidEntries( sal_Bool bCheckPopups = sal_True );
+
+ void SetItemText( sal_uInt16 nItemId, const XubString& rStr );
+ XubString GetItemText( sal_uInt16 nItemId ) const;
+@@ -291,7 +383,7 @@ public:
+ void SetItemImageAngle( sal_uInt16 nItemId, long nAngle10 );
+ long GetItemImageAngle( sal_uInt16 nItemId ) const;
+ void SetItemImageMirrorMode( sal_uInt16 nItemId, sal_Bool bMirror );
+- sal_Bool GetItemImageMirrorMode( sal_uInt16 ) const;
++ sal_Bool GetItemImageMirrorMode( sal_uInt16 ) const;
+
+ void SetItemCommand( sal_uInt16 nItemId, const XubString& rCommand );
+ const XubString& GetItemCommand( sal_uInt16 nItemId ) const;
+@@ -327,8 +419,8 @@ public:
+
+ void AddEventListener( const Link& rEventListener );
+ void RemoveEventListener( const Link& rEventListener );
+- //void AddChildEventListener( const Link& rEventListener );
+- //void RemoveChildEventListener( const Link& rEventListener );
++ void AddChildEventListener( const Link& rEventListener );
++ void RemoveChildEventListener( const Link& rEventListener );
+
+ Menu& operator =( const Menu& rMenu );
+
+@@ -367,6 +459,8 @@ public:
+
+ void HighlightItem( sal_uInt16 nItemPos );
+ void DeHighlight() { HighlightItem( 0xFFFF ); } // MENUITEMPOS_INVALID
++
++ void Freeze();
+ };
+
+ // -----------
+@@ -378,10 +472,10 @@ class VCL_DLLPUBLIC MenuBar : public Menu
+ Link maCloserHdl;
+ Link maFloatHdl;
+ Link maHideHdl;
+- sal_Bool mbCloserVisible;
+- sal_Bool mbFloatBtnVisible;
+- sal_Bool mbHideBtnVisible;
+- sal_Bool mbDisplayable;
++ sal_Bool mbCloserVisible;
++ sal_Bool mbFloatBtnVisible;
++ sal_Bool mbHideBtnVisible;
++ sal_Bool mbDisplayable;
+
+ friend class Application;
+ friend class Menu;
+@@ -391,7 +485,7 @@ class VCL_DLLPUBLIC MenuBar : public Menu
+
+ SAL_DLLPRIVATE static Window* ImplCreate( Window* pParent, Window* pWindow, MenuBar* pMenu );
+ SAL_DLLPRIVATE static void ImplDestroy( MenuBar* pMenu, sal_Bool bDelete );
+- SAL_DLLPRIVATE sal_Bool ImplHandleKeyEvent( const KeyEvent& rKEvent, sal_Bool bFromMenu = sal_True );
++ SAL_DLLPRIVATE sal_Bool ImplHandleKeyEvent( const KeyEvent& rKEvent, sal_Bool bFromMenu = sal_True );
+
+ public:
+ MenuBar();
+@@ -401,17 +495,17 @@ public:
+ MenuBar& operator =( const MenuBar& rMenu );
+
+ void ShowCloser( sal_Bool bShow = sal_True );
+- sal_Bool HasCloser() const { return mbCloserVisible; }
+- sal_Bool HasFloatButton() const { return mbFloatBtnVisible; }
+- sal_Bool HasHideButton() const { return mbHideBtnVisible; }
++ sal_Bool HasCloser() const { return mbCloserVisible; }
++ sal_Bool HasFloatButton() const { return mbFloatBtnVisible; }
++ sal_Bool HasHideButton() const { return mbHideBtnVisible; }
+ void ShowButtons( sal_Bool bClose, sal_Bool bFloat, sal_Bool bHide );
+
+ void SelectEntry( sal_uInt16 nId );
+- sal_Bool HandleMenuActivateEvent( Menu *pMenu ) const;
+- sal_Bool HandleMenuDeActivateEvent( Menu *pMenu ) const;
+- sal_Bool HandleMenuHighlightEvent( Menu *pMenu, sal_uInt16 nEventId ) const;
+- sal_Bool HandleMenuCommandEvent( Menu *pMenu, sal_uInt16 nEventId ) const;
+- sal_Bool HandleMenuButtonEvent( Menu *pMenu, sal_uInt16 nEventId ) const;
++ sal_Bool HandleMenuActivateEvent( Menu *pMenu ) const;
++ sal_Bool HandleMenuDeActivateEvent( Menu *pMenu ) const;
++ sal_Bool HandleMenuHighlightEvent( Menu *pMenu, sal_uInt16 nEventId ) const;
++ sal_Bool HandleMenuCommandEvent( Menu *pMenu, sal_uInt16 nEventId ) const;
++ sal_Bool HandleMenuButtonEvent( Menu *pMenu, sal_uInt16 nEventId ) const;
+
+ void SetCloserHdl( const Link& rLink ) { maCloserHdl = rLink; }
+ const Link& GetCloserHdl() const { return maCloserHdl; }
+@@ -425,18 +519,18 @@ public:
+ // and it will be hidden if it was visible before
+ // - note: if a menubar is diplayable, this does not necessarily mean that it is currently visible
+ void SetDisplayable( sal_Bool bDisplayable );
+- sal_Bool IsDisplayable() const { return mbDisplayable; }
++ sal_Bool IsDisplayable() const { return mbDisplayable; }
+
+ struct MenuBarButtonCallbackArg
+ {
+ sal_uInt16 nId; // Id of the button
+- bool bHighlight; // highlight on/off
+- MenuBar* pMenuBar; // menubar the button belongs to
++ bool bHighlight; // highlight on/off
++ MenuBar* pMenuBar; // menubar the button belongs to
+ };
+ // add an arbitrary button to the menubar (will appear next to closer)
+ // passed link will be call with a MenuBarButtonCallbackArg on press
+ // passed string will be set as tooltip
+- sal_uInt16 AddMenuBarButton( const Image&, const Link&, const String&, sal_uInt16 nPos = 0 );
++ sal_uInt16 AddMenuBarButton( const Image&, const Link&, const String&, sal_uInt16 nPos = 0 );
+ // set the highlight link for additional button with ID nId
+ // highlight link will be called with a MenuBarButtonHighlightArg
+ // the bHighlight member of that struct shall contain the new state
+diff --git a/vcl/source/window/menu.cxx b/vcl/source/window/menu.cxx
+index 3b4ac0d..e921805 100644
+--- a/vcl/source/window/menu.cxx
++++ b/vcl/source/window/menu.cxx
+@@ -1146,7 +1146,8 @@ void Menu::Select()
+ }
+ }
+
+-#if defined(QUARTZ)
++// FIXME: Workaround to make GLOMenu without defining macros.
++//#if defined(QUARTZ)
+ void Menu::ImplSelectWithStart( Menu* pSMenu )
+ {
+ Menu* pOldStartedFrom = pStartedFrom;
+@@ -1157,7 +1158,7 @@ void Menu::ImplSelectWithStart( Menu* pSMenu )
+ pOldStartedFrom->pStartedFrom = pOldStartedStarted;
+ pStartedFrom = pOldStartedFrom;
+ }
+-#endif
++//#endif
+
+ void Menu::RequestHelp( const HelpEvent& )
+ {
+@@ -1958,10 +1959,15 @@ sal_Bool Menu::GetItemImageMirrorMode( sal_uInt16 nItemId ) const
+
+ void Menu::SetItemCommand( sal_uInt16 nItemId, const String& rCommand )
+ {
+- MenuItemData* pData = pItemList->GetData( nItemId );
++ size_t nPos;
++ MenuItemData* pData = pItemList->GetData( nItemId, nPos );
+
+ if ( pData )
+ pData->aCommandStr = rCommand;
++
++ // update native menu
++ if( ImplGetSalMenu() && pData->pSalMenuItem )
++ ImplGetSalMenu()->SetItemCommand( nPos, pData->pSalMenuItem, rCommand );
+ }
+
+ const XubString& Menu::GetItemCommand( sal_uInt16 nItemId ) const
+@@ -3238,6 +3244,15 @@ void Menu::HighlightItem( sal_uInt16 nItemPos )
+ }
+ }
+
++void Menu::Freeze() {
++ SalMenu *pSalMenu = ImplGetSalMenu();
++
++ if ( pSalMenu ) {
++ pSalMenu->Freeze();
++ }
++}
++
++
+ // -----------
+ // - MenuBar -
+ // -----------
+diff --git a/vcl/unx/gtk/app/gtkinst.cxx b/vcl/unx/gtk/app/gtkinst.cxx
+index 845e2fc..2e00b34 100644
+--- a/vcl/unx/gtk/app/gtkinst.cxx
++++ b/vcl/unx/gtk/app/gtkinst.cxx
+@@ -38,6 +38,7 @@
+ #include <unx/gtk/gtkobject.hxx>
+ #include <unx/gtk/atkbridge.hxx>
+ #include <unx/gtk/gtkprn.hxx>
++#include <unx/gtk/gtksalmenu.hxx>
+ #include <headless/svpvd.hxx>
+ #include <headless/svpbmp.hxx>
+ #include <vcl/apptypes.hxx>
+@@ -518,6 +519,34 @@ SalBitmap* GtkInstance::CreateSalBitmap()
+ #endif
+ }
+
++SalMenu* GtkInstance::CreateMenu( sal_Bool bMenuBar, Menu* pVCLMenu )
++{
++ GtkSalMenu *pSalMenu = new GtkSalMenu( bMenuBar );
++ pSalMenu->SetMenu( pVCLMenu );
++
++ return static_cast<SalMenu*>( pSalMenu );
++}
++
++void GtkInstance::DestroyMenu( SalMenu* pMenu )
++{
++ (void)pMenu;
++ delete pMenu;
++// OSL_ENSURE( pMenu == 0, "DestroyMenu called with non-native menus" );
++}
++
++SalMenuItem* GtkInstance::CreateMenuItem( const SalItemParams* pItemData )
++{
++ GtkSalMenuItem *pMenuItem = new GtkSalMenuItem( pItemData );
++ return static_cast<SalMenuItem*>( pMenuItem );
++}
++
++void GtkInstance::DestroyMenuItem( SalMenuItem* pItem )
++{
++ (void)pItem;
++// delete pItem;
++// OSL_ENSURE( pItem == 0, "DestroyMenu called with non-native menus" );
++}
++
+ SalTimer* GtkInstance::CreateSalTimer()
+ {
+ GtkSalTimer *pTimer = new GtkSalTimer();
+diff --git a/vcl/unx/gtk/window/gloactiongroup.cxx b/vcl/unx/gtk/window/gloactiongroup.cxx
+new file mode 100644
+index 0000000..51bf2f0
+--- /dev/null
++++ b/vcl/unx/gtk/window/gloactiongroup.cxx
+@@ -0,0 +1,295 @@
++#include <unx/gtk/gloactiongroup.h>
++
++#include <unx/gtk/gtkinst.hxx>
++#include <unx/gtk/gtkframe.hxx>
++#include <unx/gtk/gtksalmenu.hxx>
++#include <vcl/menu.hxx>
++
++#include <stdio.h>
++#include <iostream>
++
++using namespace std;
++
++struct _GLOActionGroupPrivate
++{
++ GHashTable *table; /* string -> GtkSalMenuItem* */
++};
++
++static void g_lo_action_group_iface_init (GActionGroupInterface *);
++
++G_DEFINE_TYPE_WITH_CODE (GLOActionGroup,
++ g_lo_action_group, G_TYPE_OBJECT,
++ G_IMPLEMENT_INTERFACE (G_TYPE_ACTION_GROUP,
++ g_lo_action_group_iface_init));
++
++static gchar **
++g_lo_action_group_list_actions (GActionGroup *group)
++{
++ GLOActionGroup *loGroup = G_LO_ACTION_GROUP (group);
++ GHashTableIter iter;
++ gint n, i = 0;
++ gchar **keys;
++ gpointer key;
++
++ n = g_hash_table_size (loGroup->priv->table);
++ keys = g_new (gchar *, n + 1);
++
++ g_hash_table_iter_init (&iter, loGroup->priv->table);
++ while (g_hash_table_iter_next (&iter, &key, NULL))
++ keys[i++] = g_strdup ((gchar*) key);
++ g_assert_cmpint (i, ==, n);
++ keys[n] = NULL;
++
++ return keys;
++}
++
++static gboolean
++g_lo_action_group_query_action (GActionGroup *group,
++ const gchar *action_name,
++ gboolean *enabled,
++ const GVariantType **parameter_type,
++ const GVariantType **state_type,
++ GVariant **state_hint,
++ GVariant **state)
++{
++ GLOActionGroup *loGroup = G_LO_ACTION_GROUP (group);
++ GtkSalMenuItem* item_info;
++
++ item_info = static_cast< GtkSalMenuItem* >( g_hash_table_lookup (loGroup->priv->table, action_name) );
++
++ if (item_info == NULL)
++ return FALSE;
++
++ if (enabled) {
++ sal_Bool bEnabled = item_info->mpVCLMenu->IsItemEnabled( item_info->mnId );
++ *enabled = (bEnabled) ? TRUE : FALSE;
++ }
++
++ if (parameter_type)
++ *parameter_type = NULL;
++
++ if (state_type)
++ *state_type = item_info->mpStateType;
++
++ if (state_hint)
++ *state_hint = NULL;
++
++ if (state) {
++ if (item_info->mpState) {
++ g_variant_ref( item_info->mpState );
++ *state = item_info->mpState;
++ } else {
++ *state = NULL;
++ }
++ }
++
++ return TRUE;
++}
++
++static void
++g_lo_action_group_change_state (GActionGroup *group,
++ const gchar *action_name,
++ GVariant *value)
++{
++ if (!action_name || !value)
++ return;
++
++ GLOActionGroup* lo_group = G_LO_ACTION_GROUP (group);
++ GtkSalMenuItem* item_info;
++
++ item_info = static_cast<GtkSalMenuItem*>( g_hash_table_lookup (lo_group->priv->table, action_name) );
++
++ if (!item_info)
++ return;
++
++ if (!item_info->mpStateType) {
++ item_info->mpStateType = g_variant_type_copy(g_variant_get_type(value));
++ }
++
++ if (g_variant_is_of_type(value, item_info->mpStateType)) {
++ if (item_info->mpState)
++ g_variant_unref(item_info->mpState);
++
++ item_info->mpState = g_variant_new_variant(value);
++ g_action_group_action_state_changed(group, action_name, value);
++ }
++}
++
++static void
++g_lo_action_group_activate (GActionGroup *group,
++ const gchar *action_name,
++ GVariant *parameter)
++{
++ GLOActionGroup *loGroup = G_LO_ACTION_GROUP (group);
++ GtkSalMenuItem *pSalMenuItem;
++
++ pSalMenuItem = static_cast< GtkSalMenuItem* >( g_hash_table_lookup (loGroup->priv->table, action_name) );
++
++ if (pSalMenuItem == NULL || pSalMenuItem->mpSubMenu )
++ return;
++
++ GTK_YIELD_GRAB();
++
++ const GtkSalFrame *pFrame = pSalMenuItem->mpParentMenu ? pSalMenuItem->mpParentMenu->GetFrame() : NULL;
++
++ if ( pFrame && !pFrame->GetParent() ) {
++ ((PopupMenu*) pSalMenuItem->mpVCLMenu)->SetSelectedEntry( pSalMenuItem->mnId );
++ SalMenuEvent aMenuEvt( pSalMenuItem->mnId, pSalMenuItem->mpVCLMenu );
++ pFrame->CallCallback( SALEVENT_MENUCOMMAND, &aMenuEvt );
++ }
++ else if ( pSalMenuItem->mpVCLMenu )
++ {
++ // if an item from submenu was selected. the corresponding Window does not exist because
++ // we use native popup menus, so we have to set the selected menuitem directly
++ // incidentally this of course works for top level popup menus, too
++ PopupMenu * pPopupMenu = dynamic_cast<PopupMenu *>(pSalMenuItem->mpVCLMenu);
++ if( pPopupMenu )
++ {
++ // FIXME: revise this ugly code
++
++ // select handlers in vcl are dispatch on the original menu
++ // if not consumed by the select handler of the current menu
++ // however since only the starting menu ever came into Execute
++ // the hierarchy is not build up. Workaround this by getting
++ // the menu it should have been
++
++ // get started from hierarchy in vcl menus
++ GtkSalMenu* pParentMenu = pSalMenuItem->mpParentMenu;
++ Menu* pCurMenu = pSalMenuItem->mpVCLMenu;
++ while( pParentMenu && pParentMenu->GetMenu() )
++ {
++ pCurMenu = pParentMenu->GetMenu();
++ pParentMenu = pParentMenu->GetParentSalMenu();
++ }
++
++ pPopupMenu->SetSelectedEntry( pSalMenuItem->mnId );
++ pPopupMenu->ImplSelectWithStart( pCurMenu );
++ }
++ else
++ {
++ OSL_FAIL( "menubar item without frame !" );
++ }
++ }
++}
++
++void
++g_lo_action_group_insert (GLOActionGroup *group,
++ const gchar *action_name,
++ gpointer action_info)
++{
++ g_return_if_fail (G_IS_LO_ACTION_GROUP (group));
++
++ gpointer old_action;
++
++ old_action = g_hash_table_lookup (group->priv->table, action_name);
++
++ if (old_action != action_info)
++ {
++ if (old_action != NULL)
++ g_action_group_action_removed (G_ACTION_GROUP (group), action_name);
++
++ g_hash_table_insert (group->priv->table, g_strdup (action_name), action_info);
++
++ g_action_group_action_added (G_ACTION_GROUP (group), action_name);
++ }
++}
++
++static void
++g_lo_action_group_finalize (GObject *object)
++{
++ GLOActionGroup *loGroup = G_LO_ACTION_GROUP (object);
++
++ g_hash_table_unref (loGroup->priv->table);
++
++ G_OBJECT_CLASS (g_lo_action_group_parent_class)->finalize (object);
++}
++
++static void
++g_lo_action_group_init (GLOActionGroup *group)
++{
++ group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
++ G_TYPE_LO_ACTION_GROUP,
++ GLOActionGroupPrivate);
++ group->priv->table = g_hash_table_new_full (g_str_hash, g_str_equal,
++ g_free, NULL );
++}
++
++static void
++g_lo_action_group_class_init (GLOActionGroupClass *klass)
++{
++ GObjectClass *object_class = G_OBJECT_CLASS (klass);
++
++ object_class->finalize = g_lo_action_group_finalize;
++
++ g_type_class_add_private (klass, sizeof (GLOActionGroupPrivate));
++}
++
++static void
++g_lo_action_group_iface_init (GActionGroupInterface *iface)
++{
++ iface->list_actions = g_lo_action_group_list_actions;
++ iface->query_action = g_lo_action_group_query_action;
++ iface->change_action_state = g_lo_action_group_change_state;
++ iface->activate_action = g_lo_action_group_activate;
++}
++
++GLOActionGroup *
++g_lo_action_group_new (void)
++{
++ return G_LO_ACTION_GROUP( g_object_new (G_TYPE_LO_ACTION_GROUP, NULL) );
++}
++
++void
++g_lo_action_group_set_action_enabled (GLOActionGroup *group,
++ const gchar *action_name,
++ gboolean enabled)
++{
++ cout << __FUNCTION__ << " - " << action_name << endl;
++ g_return_if_fail (G_IS_LO_ACTION_GROUP (group));
++
++ g_action_group_action_enabled_changed(G_ACTION_GROUP(group),
++ action_name,
++ enabled);
++
++}
++
++void
++g_lo_action_group_remove (GLOActionGroup *group,
++ const gchar *action_name)
++{
++ g_return_if_fail (G_IS_LO_ACTION_GROUP (group));
++
++ if (action_name != NULL)
++ {
++ g_action_group_action_removed (G_ACTION_GROUP (group), action_name);
++ g_hash_table_remove (group->priv->table, action_name);
++ }
++}
++
++void
++g_lo_action_group_clear (GLOActionGroup *group)
++{
++ g_return_if_fail (G_IS_LO_ACTION_GROUP (group));
++
++ g_hash_table_remove_all(group->priv->table);
++}
++
++void
++g_lo_action_group_merge (GLOActionGroup *input_group,
++ GLOActionGroup *output_group)
++{
++ g_return_if_fail (G_IS_LO_ACTION_GROUP (input_group));
++ g_return_if_fail (G_IS_LO_ACTION_GROUP (output_group));
++ g_return_if_fail (input_group != NULL);
++ g_return_if_fail (output_group != NULL);
++
++ GHashTableIter iter;
++ gpointer key, value;
++
++ g_hash_table_iter_init (&iter, input_group->priv->table);
++
++ while (g_hash_table_iter_next (&iter, &key, &value))
++ {
++ g_lo_action_group_insert(output_group, (gchar*) key, value);
++ }
++}
+diff --git a/vcl/unx/gtk/window/glomenu.cxx b/vcl/unx/gtk/window/glomenu.cxx
+new file mode 100644
+index 0000000..7ada474
+--- /dev/null
++++ b/vcl/unx/gtk/window/glomenu.cxx
+@@ -0,0 +1,577 @@
++/*
++ * Copyright © 2011 Canonical Ltd.
++ *
++ * This library is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License as
++ * published by the Free Software Foundation; either version 2 of the
++ * licence, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
++ * USA.
++ *
++ * Author: Ryan Lortie <desrt@desrt.ca>
++ */
++
++#include <stdio.h>
++#include <string.h>
++
++#include <unx/gtk/glomenu.h>
++
++
++struct _GLOMenuItem
++{
++ GObject parent_instance;
++
++ GHashTable *attributes;
++ GHashTable *links;
++ gboolean cow;
++};
++
++typedef GObjectClass GLOMenuItemClass;
++
++struct _GLOMenu
++{
++ GMenuModel parent_instance;
++
++ GArray *items;
++// gboolean mutable;
++};
++
++typedef GMenuModelClass GLOMenuClass;
++
++G_DEFINE_TYPE (GLOMenu, g_lo_menu, G_TYPE_MENU_MODEL)
++G_DEFINE_TYPE (GLOMenuItem, g_lo_menu_item, G_TYPE_OBJECT)
++
++struct item
++{
++ GHashTable *attributes;
++ GHashTable *links;
++};
++
++static gboolean
++g_lo_menu_is_mutable (GMenuModel *model)
++{
++// GMenu *menu = G_MENU (model);
++
++// return menu->mutable;
++ return TRUE;
++}
++
++static gint
++g_lo_menu_get_n_items (GMenuModel *model)
++{
++ GLOMenu *menu = G_LO_MENU (model);
++
++ return menu->items->len;
++}
++
++static void
++g_lo_menu_get_item_attributes (GMenuModel *model,
++ gint position,
++ GHashTable **table)
++{
++ GLOMenu *menu = G_LO_MENU (model);
++
++ *table = g_hash_table_ref (g_array_index (menu->items, struct item, position).attributes);
++}
++
++static void
++g_lo_menu_get_item_links (GMenuModel *model,
++ gint position,
++ GHashTable **table)
++{
++ GLOMenu *menu = G_LO_MENU (model);
++
++ *table = g_hash_table_ref (g_array_index (menu->items, struct item, position).links);
++}
++
++void
++g_lo_menu_insert_item (GLOMenu *menu,
++ gint position,
++ GLOMenuItem *item)
++{
++ struct item new_item;
++
++ g_return_if_fail (G_IS_LO_MENU (menu));
++ g_return_if_fail (G_IS_LO_MENU_ITEM (item));
++
++ if (position < 0 || position > (gint) menu->items->len)
++ position = menu->items->len;
++
++ new_item.attributes = g_hash_table_ref (item->attributes);
++ new_item.links = g_hash_table_ref (item->links);
++ item->cow = TRUE;
++
++ g_array_insert_val (menu->items, position, new_item);
++ g_menu_model_items_changed (G_MENU_MODEL (menu), position, 0, 1);
++}
++
++void
++g_lo_menu_prepend_item (GLOMenu *menu,
++ GLOMenuItem *item)
++{
++ g_lo_menu_insert_item (menu, 0, item);
++}
++
++void
++g_lo_menu_append_item (GLOMenu *menu,
++ GLOMenuItem *item)
++{
++ g_lo_menu_insert_item (menu, -1, item);
++}
++
++void
++g_lo_menu_freeze (GLOMenu *menu)
++{
++ g_return_if_fail (G_IS_LO_MENU (menu));
++
++// menu->mutable = FALSE;
++}
++
++GLOMenu *
++g_lo_menu_new (void)
++{
++ return G_LO_MENU( g_object_new (G_TYPE_LO_MENU, NULL) );
++}
++
++void
++g_lo_menu_insert (GLOMenu *menu,
++ gint position,
++ const gchar *label,
++ const gchar *detailed_action)
++{
++ GLOMenuItem *menu_item;
++
++ menu_item = g_lo_menu_item_new (label, detailed_action);
++ g_lo_menu_insert_item (menu, position, menu_item);
++ g_object_unref (menu_item);
++}
++
++void
++g_lo_menu_prepend (GLOMenu *menu,
++ const gchar *label,
++ const gchar *detailed_action)
++{
++ g_lo_menu_insert (menu, 0, label, detailed_action);
++}
++
++void
++g_lo_menu_append (GLOMenu *menu,
++ const gchar *label,
++ const gchar *detailed_action)
++{
++ g_lo_menu_insert (menu, -1, label, detailed_action);
++}
++
++void
++g_lo_menu_insert_section (GLOMenu *menu,
++ gint position,
++ const gchar *label,
++ GMenuModel *section)
++{
++ GLOMenuItem *menu_item;
++
++ menu_item = g_lo_menu_item_new_section (label, section);
++ g_lo_menu_insert_item (menu, position, menu_item);
++ g_object_unref (menu_item);
++}
++
++void
++g_lo_menu_prepend_section (GLOMenu *menu,
++ const gchar *label,
++ GMenuModel *section)
++{
++ g_lo_menu_insert_section (menu, 0, label, section);
++}
++
++void
++g_lo_menu_append_section (GLOMenu *menu,
++ const gchar *label,
++ GMenuModel *section)
++{
++ g_lo_menu_insert_section (menu, -1, label, section);
++}
++
++void
++g_lo_menu_insert_submenu (GLOMenu *menu,
++ gint position,
++ const gchar *label,
++ GMenuModel *submenu)
++{
++ GLOMenuItem *menu_item;
++
++ menu_item = g_lo_menu_item_new_submenu (label, submenu);
++ g_lo_menu_insert_item (menu, position, menu_item);
++ g_object_unref (menu_item);
++}
++
++void
++g_lo_menu_prepend_submenu (GLOMenu *menu,
++ const gchar *label,
++ GMenuModel *submenu)
++{
++ g_lo_menu_insert_submenu (menu, 0, label, submenu);
++}
++
++void
++g_lo_menu_append_submenu (GLOMenu *menu,
++ const gchar *label,
++ GMenuModel *submenu)
++{
++ g_lo_menu_insert_submenu (menu, -1, label, submenu);
++}
++
++static void
++g_lo_menu_clear_item (struct item *item)
++{
++ if (item->attributes != NULL)
++ g_hash_table_unref (item->attributes);
++ if (item->links != NULL)
++ g_hash_table_unref (item->links);
++}
++
++void
++g_lo_menu_remove (GLOMenu *menu,
++ gint position)
++{
++ g_return_if_fail (G_IS_LO_MENU (menu));
++ g_return_if_fail (0 <= position && position < (gint) menu->items->len);
++
++ g_lo_menu_clear_item (&g_array_index (menu->items, struct item, position));
++ g_array_remove_index (menu->items, position);
++ g_menu_model_items_changed (G_MENU_MODEL (menu), position, 1, 0);
++}
++
++static void
++g_lo_menu_finalize (GObject *object)
++{
++ GLOMenu *menu = G_LO_MENU (object);
++ struct item *items;
++ gint n_items;
++ gint i;
++
++ n_items = menu->items->len;
++ items = (struct item *) g_array_free (menu->items, FALSE);
++ for (i = 0; i < n_items; i++)
++ g_lo_menu_clear_item (&items[i]);
++ g_free (items);
++
++ G_OBJECT_CLASS (g_lo_menu_parent_class)
++ ->finalize (object);
++}
++
++static void
++g_lo_menu_init (GLOMenu *menu)
++{
++ menu->items = g_array_new (FALSE, FALSE, sizeof (struct item));
++// menu->mutable = TRUE;
++}
++
++static void
++g_lo_menu_class_init (GLOMenuClass *klass)
++{
++ GMenuModelClass *model_class = G_MENU_MODEL_CLASS (klass);
++ GObjectClass *object_class = G_OBJECT_CLASS (klass);
++
++ object_class->finalize = g_lo_menu_finalize;
++
++ model_class->is_mutable = g_lo_menu_is_mutable;
++ model_class->get_n_items = g_lo_menu_get_n_items;
++ model_class->get_item_attributes = g_lo_menu_get_item_attributes;
++ model_class->get_item_links = g_lo_menu_get_item_links;
++}
++
++
++static void
++g_lo_menu_item_clear_cow (GLOMenuItem *menu_item)
++{
++ if (menu_item->cow)
++ {
++ GHashTableIter iter;
++ GHashTable *newHash;
++ gpointer key;
++ gpointer val;
++
++ newHash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_variant_unref);
++ g_hash_table_iter_init (&iter, menu_item->attributes);
++ while (g_hash_table_iter_next (&iter, &key, &val))
++ g_hash_table_insert (newHash, g_strdup ((gchar*) key), g_variant_ref ((GVariant*) val));
++ g_hash_table_unref (menu_item->attributes);
++ menu_item->attributes = newHash;
++
++ newHash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_object_unref);
++ g_hash_table_iter_init (&iter, menu_item->links);
++ while (g_hash_table_iter_next (&iter, &key, &val))
++ g_hash_table_insert (newHash, g_strdup ((gchar*) key), g_object_ref (val));
++ g_hash_table_unref (menu_item->links);
++ menu_item->links = newHash;
++
++ menu_item->cow = FALSE;
++ }
++}
++
++static void
++g_lo_menu_item_finalize (GObject *object)
++{
++ GLOMenuItem *menu_item = G_LO_MENU_ITEM (object);
++
++ g_hash_table_unref (menu_item->attributes);
++ g_hash_table_unref (menu_item->links);
++
++ G_OBJECT_CLASS (g_lo_menu_item_parent_class)
++ ->finalize (object);
++}
++
++static void
++g_lo_menu_item_init (GLOMenuItem *menu_item)
++{
++ menu_item->attributes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_variant_unref);
++ menu_item->links = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
++ menu_item->cow = FALSE;
++}
++
++static void
++g_lo_menu_item_class_init (GLOMenuItemClass *klass)
++{
++ klass->finalize = g_lo_menu_item_finalize;
++}
++
++/* We treat attribute names the same as GSettings keys:
++ * - only lowercase ascii, digits and '-'
++ * - must start with lowercase
++ * - must not end with '-'
++ * - no consecutive '-'
++ * - not longer than 1024 chars
++ */
++static gboolean
++valid_attribute_name (const gchar *name)
++{
++ gint i;
++
++ if (!g_ascii_islower (name[0]))
++ return FALSE;
++
++ for (i = 1; name[i]; i++)
++ {
++ if (name[i] != '-' &&
++ !g_ascii_islower (name[i]) &&
++ !g_ascii_isdigit (name[i]))
++ return FALSE;
++
++ if (name[i] == '-' && name[i + 1] == '-')
++ return FALSE;
++ }
++
++ if (name[i - 1] == '-')
++ return FALSE;
++
++ if (i > 1024)
++ return FALSE;
++
++ return TRUE;
++}
++
++void
++g_lo_menu_item_set_attribute_value (GLOMenuItem *menu_item,
++ const gchar *attribute,
++ GVariant *value)
++{
++ g_return_if_fail (G_IS_LO_MENU_ITEM (menu_item));
++ g_return_if_fail (attribute != NULL);
++ g_return_if_fail (valid_attribute_name (attribute));
++
++ g_lo_menu_item_clear_cow (menu_item);
++
++ if (value != NULL)
++ g_hash_table_insert (menu_item->attributes, g_strdup (attribute), g_variant_ref_sink (value));
++ else
++ g_hash_table_remove (menu_item->attributes, attribute);
++}
++
++void
++g_lo_menu_item_set_attribute (GLOMenuItem *menu_item,
++ const gchar *attribute,
++ const gchar *format_string,
++ ...)
++{
++ GVariant *value;
++
++ if (format_string != NULL)
++ {
++ va_list ap;
++
++ va_start (ap, format_string);
++ value = g_variant_new_va (format_string, NULL, &ap);
++ va_end (ap);
++ }
++ else
++ value = NULL;
++
++ g_lo_menu_item_set_attribute_value (menu_item, attribute, value);
++}
++
++void
++g_lo_menu_item_set_link (GLOMenuItem *menu_item,
++ const gchar *link,
++ GMenuModel *model)
++{
++ g_return_if_fail (G_IS_LO_MENU_ITEM (menu_item));
++ g_return_if_fail (link != NULL);
++ g_return_if_fail (valid_attribute_name (link));
++
++ g_lo_menu_item_clear_cow (menu_item);
++
++ if (model != NULL)
++ g_hash_table_insert (menu_item->links, g_strdup (link), g_object_ref (model));
++ else
++ g_hash_table_remove (menu_item->links, link);
++}
++
++void
++g_lo_menu_item_set_label (GLOMenuItem *menu_item,
++ const gchar *label)
++{
++ GVariant *value;
++
++ if (label != NULL)
++ value = g_variant_new_string (label);
++ else
++ value = NULL;
++
++ g_lo_menu_item_set_attribute_value (menu_item, G_MENU_ATTRIBUTE_LABEL, value);
++}
++
++void
++g_lo_menu_item_set_submenu (GLOMenuItem *menu_item,
++ GMenuModel *submenu)
++{
++ g_lo_menu_item_set_link (menu_item, G_MENU_LINK_SUBMENU, submenu);
++}
++
++void
++g_lo_menu_item_set_section (GLOMenuItem *menu_item,
++ GMenuModel *section)
++{
++ g_lo_menu_item_set_link (menu_item, G_MENU_LINK_SECTION, section);
++}
++
++void
++g_lo_menu_item_set_action_and_target_value (GLOMenuItem *menu_item,
++ const gchar *action,
++ GVariant *target_value)
++{
++ GVariant *action_value;
++
++ if (action != NULL)
++ {
++ action_value = g_variant_new_string (action);
++ }
++ else
++ {
++ action_value = NULL;
++ target_value = NULL;
++ }
++
++ g_lo_menu_item_set_attribute_value (menu_item, G_MENU_ATTRIBUTE_ACTION, action_value);
++ g_lo_menu_item_set_attribute_value (menu_item, G_MENU_ATTRIBUTE_TARGET, target_value);
++}
++
++void
++g_lo_menu_item_set_action_and_target (GLOMenuItem *menu_item,
++ const gchar *action,
++ const gchar *format_string,
++ ...)
++{
++ GVariant *value;
++
++ if (format_string != NULL)
++ {
++ va_list ap;
++
++ va_start (ap, format_string);
++ value = g_variant_new_va (format_string, NULL, &ap);
++ va_end (ap);
++ }
++ else
++ value = NULL;
++
++ g_lo_menu_item_set_action_and_target_value (menu_item, action, value);
++}
++
++void
++g_lo_menu_item_set_detailed_action (GLOMenuItem *menu_item,
++ const gchar *detailed_action)
++{
++ const gchar *sep;
++
++ sep = strstr (detailed_action, "::");
++
++ if (sep != NULL)
++ {
++ gchar *action;
++
++ action = g_strndup (detailed_action, sep - detailed_action);
++ g_lo_menu_item_set_action_and_target (menu_item, action, "s", sep + 2);
++ g_free (action);
++ }
++
++ else
++ g_lo_menu_item_set_action_and_target_value (menu_item, detailed_action, NULL);
++}
++
++GLOMenuItem *
++g_lo_menu_item_new (const gchar *label,
++ const gchar *detailed_action)
++{
++ GLOMenuItem *menu_item;
++
++ menu_item = G_LO_MENU_ITEM( g_object_new (G_TYPE_LO_MENU_ITEM, NULL) );
++
++ if (label != NULL)
++ g_lo_menu_item_set_label (menu_item, label);
++
++ if (detailed_action != NULL)
++ g_lo_menu_item_set_detailed_action (menu_item, detailed_action);
++
++ return menu_item;
++}
++
++GLOMenuItem *
++g_lo_menu_item_new_submenu (const gchar *label,
++ GMenuModel *submenu)
++{
++ GLOMenuItem *menu_item;
++
++ menu_item = G_LO_MENU_ITEM( g_object_new (G_TYPE_LO_MENU_ITEM, NULL) );
++
++ if (label != NULL)
++ g_lo_menu_item_set_label (menu_item, label);
++
++ g_lo_menu_item_set_submenu (menu_item, submenu);
++
++ return menu_item;
++}
++
++GLOMenuItem *
++g_lo_menu_item_new_section (const gchar *label,
++ GMenuModel *section)
++{
++ GLOMenuItem *menu_item;
++
++ menu_item = G_LO_MENU_ITEM( g_object_new (G_TYPE_LO_MENU_ITEM, NULL) );
++
++ if (label != NULL)
++ g_lo_menu_item_set_label (menu_item, label);
++
++ g_lo_menu_item_set_section (menu_item, section);
++
++ return menu_item;
++}
++
+diff --git a/vcl/unx/gtk/window/gtksalmenu.cxx b/vcl/unx/gtk/window/gtksalmenu.cxx
+new file mode 100644
+index 0000000..a82dbe2
+--- /dev/null
++++ b/vcl/unx/gtk/window/gtksalmenu.cxx
+@@ -0,0 +1,511 @@
++
++#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>
++
++#include <iostream>
++
++using namespace std;
++
++//Some menus are special, this is the list of them
++gboolean
++isSpecialSubmenu (OUString command)
++{
++ const gchar * specialSubmenus[11] = {".uno:CharFontName",
++ ".uno:FontHeight",
++ ".uno:ObjectMenue",
++ ".uno:InsertPageHeader",
++ ".uno:InsertPageFooter",
++ ".uno:ChangeControlType",
++ ".uno:AvailableToolbars",
++ ".uno:ScriptOrganizer",
++ ".uno:RecentFileList",
++ ".uno:AddDirect",
++ ".uno:AutoPilotMenu"};
++
++ for (gint i = 0; i < 11; i++)
++ {
++ if (command.equals (OUString::createFromAscii (specialSubmenus[i])))
++ return TRUE;
++ }
++ return FALSE;
++}
++
++void updateNativeMenu( GtkSalMenu* pMenu ) {
++ if ( pMenu ) {
++ for ( sal_uInt16 i = 0; i < pMenu->GetItemCount(); i++ ) {
++ GtkSalMenuItem* pSalMenuItem = pMenu->GetItemAtPos( i );
++
++ if ( !pSalMenuItem->mpVCLMenu )
++ continue;
++
++ String aText = pSalMenuItem->mpVCLMenu->GetItemText( pSalMenuItem->mnId );
++
++ // Force updating of native menu labels.
++ pMenu->SetItemText( i, pSalMenuItem, aText );
++
++ if ( pSalMenuItem->mpSubMenu && pSalMenuItem->mpSubMenu->GetMenu() ) {
++ pSalMenuItem->mpSubMenu->GetMenu()->Activate();
++ updateNativeMenu( pSalMenuItem->mpSubMenu );
++
++ // FIXME: Using Deactivate() let the menu to update itself correctly, but generates
++ // duplicated popup menus.
++// pSalMenuItem->mpSubMenu->GetMenu()->Deactivate();
++ }
++ }
++ }
++}
++
++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));
++ }
++}
++
++GActionGroup* GetActionGroupFromMenubar( GtkSalMenu *pMenu )
++{
++ GtkSalMenu *pSalMenu = pMenu;
++
++ while ( pSalMenu && pSalMenu->GetParentSalMenu() )
++ pSalMenu = pSalMenu->GetParentSalMenu();
++
++ return ( pSalMenu ) ? pSalMenu->GetActionGroup() : NULL;
++}
++
++/*
++ * GtkSalMenu
++ */
++
++GtkSalMenuItem* GtkSalMenu::GetSalMenuItem( sal_uInt16 nId )
++{
++ for ( sal_uInt16 i = 0; i < maItems.size(); i++ )
++ {
++ GtkSalMenuItem* pSalMenuItem = maItems[ i ];
++
++ if ( pSalMenuItem->mnId == nId ) {
++ return pSalMenuItem;
++ }
++
++ if ( pSalMenuItem->mpSubMenu )
++ {
++ pSalMenuItem = pSalMenuItem->mpSubMenu->GetSalMenuItem( nId );
++ if (pSalMenuItem) {
++ return pSalMenuItem;
++ }
++ }
++ }
++
++ return NULL;
++}
++
++sal_Int16 GtkSalMenu::GetSectionNumber( GMenuModel* pSection )
++{
++ if ( pSection == NULL )
++ return -1;
++
++ for ( int i = 0; maSections.size(); i++ )
++ {
++ if ( maSections[ i ] == pSection )
++ return i;
++ }
++
++ return -1;
++}
++
++GtkSalMenu::GtkSalMenu( sal_Bool bMenuBar ) :
++ mbMenuBar( bMenuBar ),
++ mpVCLMenu( NULL ),
++ mpParentSalMenu( NULL ),
++ mpFrame( NULL ),
++ pSessionBus( NULL ),
++ mMenubarId( 0 ),
++ mActionGroupId ( 0 ),
++ mpMenuModel( NULL ),
++ mpActionGroup( NULL )
++{
++ mpCurrentSection = G_MENU_MODEL( g_lo_menu_new() );
++ maSections.push_back( mpCurrentSection );
++
++ if (bMenuBar) {
++ mpActionGroup = G_ACTION_GROUP( g_lo_action_group_new() );
++
++ pSessionBus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
++ if(!pSessionBus) puts ("Fail bus get");
++ } else {
++ mpMenuModel = G_MENU_MODEL( g_lo_menu_new() );
++ g_lo_menu_append_section( G_LO_MENU( mpMenuModel ), NULL, mpCurrentSection );
++ }
++}
++
++GtkSalMenu::~GtkSalMenu()
++{
++ g_source_remove_by_user_data( this );
++
++ g_object_unref( mpCurrentSection );
++
++ if ( mbMenuBar ) {
++ g_lo_menu_remove( G_LO_MENU( mpMenuModel ), 0 );
++ mpMenuModel = NULL;
++ } else {
++ g_object_unref( mpMenuModel );
++ }
++
++ if ( mpActionGroup ) {
++ g_lo_action_group_clear( G_LO_ACTION_GROUP( mpActionGroup ) );
++ }
++
++ pSessionBus = NULL;
++
++ maSections.clear();
++ maItems.clear();
++}
++
++sal_Bool GtkSalMenu::VisibleMenuBar()
++{
++ return sal_False;
++}
++
++void GtkSalMenu::InsertItem( SalMenuItem* pSalMenuItem, unsigned nPos )
++{
++ GtkSalMenuItem *pGtkSalMenuItem = static_cast<GtkSalMenuItem*>( pSalMenuItem );
++
++ maItems.push_back( pGtkSalMenuItem );
++
++ if ( pGtkSalMenuItem->mpMenuItem ) {
++ if ( !mpCurrentSection ) {
++ mpCurrentSection = G_MENU_MODEL( g_lo_menu_new() );
++ maSections.push_back( mpCurrentSection );
++
++ if ( mpMenuModel ) {
++ g_lo_menu_append_section( G_LO_MENU( mpMenuModel ), NULL, mpCurrentSection );
++ }
++ }
++
++ pGtkSalMenuItem->mpParentSection = mpCurrentSection;
++ pGtkSalMenuItem->mnPos = g_menu_model_get_n_items( mpCurrentSection );
++
++ g_lo_menu_insert_item( G_LO_MENU( mpCurrentSection ), pGtkSalMenuItem->mnPos, pGtkSalMenuItem->mpMenuItem );
++ } else {
++ // If no mpMenuItem exists, then item is a separator.
++ mpCurrentSection = G_MENU_MODEL( g_lo_menu_new() );
++ maSections.push_back( mpCurrentSection );
++
++ if ( mpMenuModel ) {
++ g_lo_menu_append_section( G_LO_MENU( mpMenuModel ), NULL, mpCurrentSection );
++ }
++ }
++
++ pGtkSalMenuItem->mpParentMenu = this;
++}
++
++void GtkSalMenu::RemoveItem( unsigned nPos )
++{
++ // FIXME: This method makes the application crash.
++// GtkSalMenuItem* pSalMenuItem = maItems[ nPos ];
++
++// GLOActionGroup* pActionGroup = G_LO_ACTION_GROUP( GetActionGroupFromMenubar( this ) );
++// if ( pActionGroup ) {
++// g_lo_action_group_remove( pActionGroup, pSalMenuItem->maCommand );
++// }
++
++// cout << __FUNCTION__ << " - " << pSalMenuItem->mpParentSection << " - " << pSalMenuItem->mnPos << endl;
++
++// if ( pSalMenuItem->mpParentSection ) {
++// if ( GetSectionNumber( pSalMenuItem->mpParentSection ) > -1 )
++// g_lo_menu_remove( G_LO_MENU( pSalMenuItem->mpParentSection ), pSalMenuItem->mnPos );
++
++// if ( g_menu_model_get_n_items( pSalMenuItem->mpParentSection ) == 0 ) {
++// sal_uInt16 nSection = GetSectionNumber( pSalMenuItem->mpParentSection );
++
++// cout << "Removing section " << nSection << endl;
++
++// g_lo_menu_remove( G_LO_MENU( mpMenuModel ), nSection );
++// maSections.erase( maSections.begin() + nSection, maSections.begin() + nSection );
++
++// if ( pSalMenuItem->mpParentSection == mpCurrentSection )
++// mpCurrentSection = maSections.back();
++// }
++// }
++
++// maItems.erase( maItems.begin() + nPos, maItems.begin() + nPos );
++}
++
++void GtkSalMenu::SetSubMenu( SalMenuItem* pSalMenuItem, SalMenu* pSubMenu, unsigned nPos )
++{
++ GtkSalMenuItem *pGtkSalMenuItem = static_cast<GtkSalMenuItem*>( pSalMenuItem );
++ GtkSalMenu *pGtkSubMenu = static_cast<GtkSalMenu*>( pSubMenu );
++
++ if ( pGtkSubMenu ) {
++ pGtkSalMenuItem->mpSubMenu = pGtkSubMenu;
++ g_lo_menu_item_set_submenu( pGtkSalMenuItem->mpMenuItem, pGtkSubMenu->mpMenuModel );
++
++ if ( !pGtkSubMenu->mpParentSalMenu ) {
++ pGtkSubMenu->mpParentSalMenu = this;
++ }
++ }
++}
++
++void GtkSalMenu::SetFrame( const SalFrame* pFrame )
++{
++ mpFrame = static_cast<const GtkSalFrame*>( pFrame );
++
++ GtkWidget *widget = GTK_WIDGET( mpFrame->getWindow() );
++
++ GdkWindow *gdkWindow = gtk_widget_get_window( widget );
++
++ if (gdkWindow) {
++ gpointer pMenu = g_object_get_data( G_OBJECT( gdkWindow ), "g-lo-menubar" );
++ GLOActionGroup* pActionGroup = G_LO_ACTION_GROUP( g_object_get_data( G_OBJECT( gdkWindow ), "g-lo-action-group" ) );
++
++ if ( pMenu && pActionGroup ) {
++ mpMenuModel = G_MENU_MODEL( pMenu );
++
++ // Merge current action group with the exported one
++ g_lo_action_group_clear( pActionGroup );
++ g_lo_action_group_merge( G_LO_ACTION_GROUP( mpActionGroup ), pActionGroup );
++ g_lo_action_group_clear( G_LO_ACTION_GROUP( mpActionGroup ) );
++ g_object_unref( mpActionGroup );
++
++ mpActionGroup = G_ACTION_GROUP( pActionGroup );
++ } else {
++ mpMenuModel = G_MENU_MODEL( g_lo_menu_new() );
++
++ 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 );
++
++ 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 );
++
++ 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 );
++
++ // Publish the menu.
++ if ( aDBusMenubarPath ) {
++ mMenubarId = g_dbus_connection_export_menu_model (pSessionBus, aDBusMenubarPath, mpMenuModel, NULL);
++ if(!mMenubarId) puts("Fail export menubar");
++ }
++
++ if ( aDBusPath ) {
++ mActionGroupId = g_dbus_connection_export_action_group( pSessionBus, aDBusPath, mpActionGroup, NULL);
++ }
++
++ g_free( aDBusPath );
++ g_free( aDBusWindowPath );
++ g_free( aDBusMenubarPath );
++ }
++
++ g_lo_menu_append_section( G_LO_MENU( mpMenuModel ), NULL, mpCurrentSection );
++
++ // Refresh the menu every second.
++ // This code is a workaround until required modifications in Gtk+ are available.
++ g_timeout_add_seconds( 1, GenerateMenu, this );
++ }
++}
++
++const GtkSalFrame* GtkSalMenu::GetFrame() const
++{
++ const GtkSalMenu* pMenu = this;
++ while( pMenu && ! pMenu->mpFrame )
++ pMenu = pMenu->mpParentSalMenu;
++ return pMenu ? pMenu->mpFrame : NULL;
++}
++
++void GtkSalMenu::CheckItem( unsigned nPos, sal_Bool bCheck )
++{
++// cout << __FUNCTION__ << " - " << nPos << " - " << bCheck << endl;
++// GActionGroup* pActionGroup = GetActionGroupFromMenubar( this );
++
++// if ( !pActionGroup )
++// return;
++
++// GtkSalMenuItem* pSalMenuItem = maItems[ nPos ];
++
++// if ( !pSalMenuItem || pSalMenuItem->mpSubMenu )
++// return;
++
++// MenuItemBits itemBits = pSalMenuItem->mnBits;
++// GVariant *pCheckValue = NULL;
++
++// if ( itemBits & MIB_CHECKABLE ) {
++// gboolean bCheckedValue = ( bCheck == sal_True ) ? TRUE : FALSE;
++// pCheckValue = g_variant_new_boolean( bCheckedValue );
++// }
++
++// if ( pCheckValue )
++// g_action_group_change_action_state( pActionGroup, pSalMenuItem->maCommand, pCheckValue );
++}
++
++void GtkSalMenu::EnableItem( unsigned nPos, sal_Bool bEnable )
++{
++ GLOActionGroup* pActionGroup = G_LO_ACTION_GROUP( GetActionGroupFromMenubar( this ) );
++
++ if ( pActionGroup ) {
++ GtkSalMenuItem* pSalMenuItem = maItems[ nPos ];
++
++ gboolean bItemEnabled = (bEnable == sal_True) ? TRUE : FALSE;
++
++ if ( g_strcmp0( pSalMenuItem->maCommand, "" ) == 0 )
++ return;
++
++ g_lo_action_group_set_action_enabled( pActionGroup, pSalMenuItem->maCommand, bItemEnabled );
++ }
++}
++
++void GtkSalMenu::SetItemText( unsigned nPos, SalMenuItem* pSalMenuItem, const rtl::OUString& rText )
++{
++ // Replace the "~" character with "_".
++ rtl::OUString aText = rText.replace( '~', '_' );
++ rtl::OString aConvertedText = OUStringToOString(aText, RTL_TEXTENCODING_UTF8);
++
++ GtkSalMenuItem *pGtkSalMenuItem = static_cast<GtkSalMenuItem*>( pSalMenuItem );
++
++ GLOMenuItem *pMenuItem = G_LO_MENU_ITEM( pGtkSalMenuItem->mpMenuItem );
++
++ GVariant* aCurrentLabel = g_menu_model_get_item_attribute_value( pGtkSalMenuItem->mpParentSection, pGtkSalMenuItem->mnPos, G_MENU_ATTRIBUTE_LABEL, G_VARIANT_TYPE_STRING );
++
++ sal_Bool bSetLabel = sal_True;
++
++ if ( aCurrentLabel ) {
++ if ( g_strcmp0( g_variant_get_string( aCurrentLabel, NULL ), aConvertedText.getStr() ) == 0 ) {
++ bSetLabel = sal_False;
++ }
++ }
++
++ if ( bSetLabel == sal_True ) {
++ g_lo_menu_item_set_label( pMenuItem, aConvertedText.getStr() );
++
++ if ( pGtkSalMenuItem->mpParentSection ) {
++ g_lo_menu_remove( G_LO_MENU( pGtkSalMenuItem->mpParentSection ), pGtkSalMenuItem->mnPos );
++ g_lo_menu_insert_item( G_LO_MENU( pGtkSalMenuItem->mpParentSection ), pGtkSalMenuItem->mnPos, pGtkSalMenuItem->mpMenuItem );
++ }
++ }
++}
++
++void GtkSalMenu::SetItemImage( unsigned nPos, SalMenuItem* pSalMenuItem, const Image& rImage)
++{
++}
++
++void GtkSalMenu::SetAccelerator( unsigned nPos, SalMenuItem* pSalMenuItem, const KeyCode& rKeyCode, const rtl::OUString& rKeyName )
++{
++}
++
++void GtkSalMenu::SetItemCommand( unsigned nPos, SalMenuItem* pSalMenuItem, const rtl::OUString& aCommandStr )
++{
++ GtkSalMenuItem* pGtkSalMenuItem = static_cast< GtkSalMenuItem* >( pSalMenuItem );
++
++ if ( pGtkSalMenuItem && pGtkSalMenuItem->mpMenuItem ) {
++ rtl::OString aOCommandStr = rtl::OUStringToOString( aCommandStr, RTL_TEXTENCODING_UTF8 );
++
++ if ( pGtkSalMenuItem->maCommand )
++ g_free( pGtkSalMenuItem->maCommand );
++
++ pGtkSalMenuItem->maCommand = g_strdup( aOCommandStr.getStr() );
++
++ GLOActionGroup* pActionGroup = G_LO_ACTION_GROUP( GetActionGroupFromMenubar( this ) );
++ if ( !pGtkSalMenuItem->mpVCLMenu->GetPopupMenu( pGtkSalMenuItem->mnId ) && pActionGroup ) {
++ g_lo_action_group_insert( pActionGroup, pGtkSalMenuItem->maCommand, pGtkSalMenuItem );
++ }
++
++ gchar* aItemCommand = g_strconcat("win.", pGtkSalMenuItem->maCommand, NULL );
++
++ g_lo_menu_item_set_action_and_target( pGtkSalMenuItem->mpMenuItem, aItemCommand, NULL );
++
++ g_free( aItemCommand );
++
++ if ( pGtkSalMenuItem->mpParentSection ) {
++ g_lo_menu_remove( G_LO_MENU( pGtkSalMenuItem->mpParentSection ), pGtkSalMenuItem->mnPos );
++ g_lo_menu_insert_item( G_LO_MENU( pGtkSalMenuItem->mpParentSection ), pGtkSalMenuItem->mnPos, pGtkSalMenuItem->mpMenuItem );
++ }
++ }
++}
++
++void GtkSalMenu::GetSystemMenuData( SystemMenuData* pData )
++{
++}
++
++void GtkSalMenu::Freeze()
++{
++}
++
++// =======================================================================
++
++/*
++ * GtkSalMenuItem
++ */
++
++GtkSalMenuItem::GtkSalMenuItem( const SalItemParams* pItemData ) :
++ mnId( pItemData->nId ),
++ mnBits( pItemData->nBits ),
++ mnPos( 0 ),
++ maCommand( NULL ),
++ mpVCLMenu( pItemData->pMenu ),
++ mpParentMenu( NULL ),
++ mpSubMenu( NULL ),
++ mpMenuItem( NULL ),
++ mpStateType( NULL ),
++ mpState( NULL )
++{
++ if ( pItemData->eType != MENUITEM_SEPARATOR ) {
++ mpMenuItem = g_lo_menu_item_new( "EMPTY STRING", NULL );
++
++ maCommand = g_strdup( rtl::OUStringToOString( mpVCLMenu->GetItemCommand( mnId ), RTL_TEXTENCODING_UTF8 ).getStr() );
++ gchar* aActionCommand = g_strconcat( "win.", maCommand, NULL );
++ g_lo_menu_item_set_action_and_target( mpMenuItem, aActionCommand, NULL );
++
++ g_free( aActionCommand );
++ }
++}
++
++GtkSalMenuItem::~GtkSalMenuItem()
++{
++
++ if ( mpMenuItem ) {
++ g_object_unref( mpMenuItem );
++ g_free( maCommand );
++ }
++}
+diff --git a/vcl/unx/gtk3/window/gtk3gloactiongroup.cxx b/vcl/unx/gtk3/window/gtk3gloactiongroup.cxx
+new file mode 100644
+index 0000000..14a2bbb
+--- /dev/null
++++ b/vcl/unx/gtk3/window/gtk3gloactiongroup.cxx
+@@ -0,0 +1,2 @@
++
++#include "../../gtk/window/gloactiongroup.cxx"
+diff --git a/vcl/unx/gtk3/window/gtk3glomenu.cxx b/vcl/unx/gtk3/window/gtk3glomenu.cxx
+new file mode 100644
+index 0000000..3736ac4
+--- /dev/null
++++ b/vcl/unx/gtk3/window/gtk3glomenu.cxx
+@@ -0,0 +1,2 @@
++
++#include "../../gtk/window/glomenu.cxx"
+diff --git a/vcl/unx/gtk3/window/gtk3gtksalmenu.cxx b/vcl/unx/gtk3/window/gtk3gtksalmenu.cxx
+new file mode 100644
+index 0000000..d6c7abe
+--- /dev/null
++++ b/vcl/unx/gtk3/window/gtk3gtksalmenu.cxx
+@@ -0,0 +1,2 @@
++
++#include "../../gtk/window/gtksalmenu.cxx"
--
LibreOffice packaging repository
Reply to: