summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2015-02-04 14:02:41 +0000
committerCaolán McNamara <caolanm@redhat.com>2015-02-04 16:34:53 +0000
commit4904180247c0d5745a393e3cd57eaae29f3837e5 (patch)
treedcdc86ab3f80de6bed1a8d57fe3786084be625f3
parent0c3505f01a792449b0c6bf81f518e7a062eea146 (diff)
fix leak from framework::AddonMenuManager::BuildMenu
provide a callback when a menu item gets deleted Change-Id: I5b5f1a181fb10f53f6b1fe7b5637d385e1517530
-rw-r--r--framework/inc/uielement/newmenucontroller.hxx4
-rw-r--r--framework/source/fwe/classes/addonmenu.cxx6
-rw-r--r--framework/source/fwe/classes/bmkmenu.cxx4
-rw-r--r--framework/source/fwe/xml/menuconfiguration.cxx22
-rw-r--r--framework/source/uielement/menubarmanager.cxx5
-rw-r--r--framework/source/uielement/newmenucontroller.cxx31
-rw-r--r--include/framework/menuconfiguration.hxx36
-rw-r--r--include/vcl/menu.hxx6
-rw-r--r--vcl/source/window/menu.cxx11
-rw-r--r--vcl/source/window/menuitemlist.cxx2
-rw-r--r--vcl/source/window/menuitemlist.hxx5
11 files changed, 92 insertions, 40 deletions
diff --git a/framework/inc/uielement/newmenucontroller.hxx b/framework/inc/uielement/newmenucontroller.hxx
index ad802fa0ff2a..a86d5ad97e9f 100644
--- a/framework/inc/uielement/newmenucontroller.hxx
+++ b/framework/inc/uielement/newmenucontroller.hxx
@@ -81,9 +81,6 @@ namespace framework
private:
virtual void impl_setPopupMenu() SAL_OVERRIDE;
- typedef MenuConfiguration::Attributes AddInfo;
-
- typedef std::unordered_map< int, std::unique_ptr<AddInfo> > AddInfoForId;
void fillPopupMenu( com::sun::star::uno::Reference< com::sun::star::awt::XPopupMenu >& rPopupMenu );
void retrieveShortcutsFromConfiguration( const ::com::sun::star::uno::Reference< ::com::sun::star::ui::XAcceleratorConfiguration >& rAccelCfg,
@@ -99,7 +96,6 @@ namespace framework
m_bNewMenu : 1,
m_bModuleIdentified : 1,
m_bAcceleratorCfg : 1;
- AddInfoForId m_aAddInfoForItem;
OUString m_aTargetFrame;
OUString m_aModuleIdentifier;
OUString m_aEmptyDocURL;
diff --git a/framework/source/fwe/classes/addonmenu.cxx b/framework/source/fwe/classes/addonmenu.cxx
index 460104a9d119..54c1fa9089a8 100644
--- a/framework/source/fwe/classes/addonmenu.cxx
+++ b/framework/source/fwe/classes/addonmenu.cxx
@@ -58,10 +58,7 @@ AddonMenu::~AddonMenu()
{
if ( GetItemType( i ) != MenuItemType::SEPARATOR )
{
- // delete user attributes created with new!
sal_uInt16 nId = GetItemId( i );
- MenuConfiguration::Attributes* pUserAttributes = reinterpret_cast<MenuConfiguration::Attributes*>(GetUserValue( nId ));
- delete pUserAttributes;
delete GetPopupMenu( nId );
}
}
@@ -333,7 +330,8 @@ void AddonMenuManager::BuildMenu( PopupMenu* pCurrent
// Store values from configuration to the New and Wizard menu entries to enable
// sfx2 based code to support high contrast mode correctly!
- pCurrentMenu->SetUserValue( nId, sal_uIntPtr( new MenuConfiguration::Attributes( aTarget, aImageId )) );
+ sal_uIntPtr nAttributePtr = MenuConfiguration::Attributes::CreateAttribute(aTarget, aImageId);
+ pCurrentMenu->SetUserValue(nId, nAttributePtr, MenuConfiguration::Attributes::ReleaseAttribute);
pCurrentMenu->SetItemCommand( nId, aURL );
if ( pSubMenu )
diff --git a/framework/source/fwe/classes/bmkmenu.cxx b/framework/source/fwe/classes/bmkmenu.cxx
index bf1396b2c5dd..a3f42905b536 100644
--- a/framework/source/fwe/classes/bmkmenu.cxx
+++ b/framework/source/fwe/classes/bmkmenu.cxx
@@ -164,8 +164,8 @@ void BmkMenu::Initialize()
else
InsertItem( nId, aTitle );
- MenuConfiguration::Attributes* pUserAttributes = new MenuConfiguration::Attributes( aTargetFrame, aImageId );
- SetUserValue( nId, reinterpret_cast<sal_uIntPtr>(pUserAttributes) );
+ sal_uIntPtr nAttributePtr = MenuConfiguration::Attributes::CreateAttribute(aTargetFrame, aImageId);
+ SetUserValue(nId, nAttributePtr, MenuConfiguration::Attributes::ReleaseAttribute);
SetItemCommand( nId, aURL );
}
diff --git a/framework/source/fwe/xml/menuconfiguration.cxx b/framework/source/fwe/xml/menuconfiguration.cxx
index 8eb6a6d7731c..aabbc47b9751 100644
--- a/framework/source/fwe/xml/menuconfiguration.cxx
+++ b/framework/source/fwe/xml/menuconfiguration.cxx
@@ -139,6 +139,28 @@ void MenuConfiguration::StoreMenuBarConfigurationToXML(
}
}
+sal_uIntPtr MenuConfiguration::Attributes::CreateAttribute(const OUString& rFrame, const OUString& rImageIdStr)
+{
+ Attributes* pAttributes = new Attributes(rFrame, rImageIdStr);
+ pAttributes->acquire();
+ return reinterpret_cast<sal_uIntPtr>(pAttributes);
+}
+
+sal_uIntPtr MenuConfiguration::Attributes::CreateAttribute(const css::uno::WeakReference<css::frame::XDispatchProvider>& rDispatchProvider)
+{
+ Attributes* pAttributes = new Attributes(rDispatchProvider);
+ pAttributes->acquire();
+ return reinterpret_cast<sal_uIntPtr>(pAttributes);
+}
+
+void MenuConfiguration::Attributes::ReleaseAttribute(sal_uIntPtr nAttributePtr)
+{
+ if (!nAttributePtr)
+ return;
+ Attributes* pAttributes = reinterpret_cast<Attributes*>(nAttributePtr);
+ pAttributes->release();
+}
+
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/framework/source/uielement/menubarmanager.cxx b/framework/source/uielement/menubarmanager.cxx
index 4fe9415c48a1..d97c96d85aa2 100644
--- a/framework/source/uielement/menubarmanager.cxx
+++ b/framework/source/uielement/menubarmanager.cxx
@@ -1687,9 +1687,8 @@ void MenuBarManager::FillMenu(
if ( xDispatchProvider.is() )
{
// Use attributes struct to transport special dispatch provider
- MenuConfiguration::Attributes* pAttributes = new MenuConfiguration::Attributes;
- pAttributes->xDispatchProvider = xDispatchProvider;
- pMenu->SetUserValue( nId, reinterpret_cast<sal_uIntPtr>( pAttributes ));
+ sal_uIntPtr nAttributePtr = MenuConfiguration::Attributes::CreateAttribute(xDispatchProvider);
+ pMenu->SetUserValue(nId, nAttributePtr, MenuConfiguration::Attributes::ReleaseAttribute);
}
// Use help command to transport module identifier
diff --git a/framework/source/uielement/newmenucontroller.cxx b/framework/source/uielement/newmenucontroller.cxx
index 216c7a1c1762..12e13fa02292 100644
--- a/framework/source/uielement/newmenucontroller.cxx
+++ b/framework/source/uielement/newmenucontroller.cxx
@@ -83,9 +83,10 @@ void NewMenuController::setMenuImages( PopupMenu* pPopupMenu, bool bSetImages )
bool bImageSet( false );
OUString aImageId;
- AddInfoForId::const_iterator pInfo = m_aAddInfoForItem.find( nItemId );
- if ( pInfo != m_aAddInfoForItem.end() )
- aImageId = pInfo->second->aImageId; // Retrieve image id for menu item
+ sal_uIntPtr nAttributePtr = pPopupMenu->GetUserValue(sal::static_int_cast<sal_uInt16>(i));
+ MenuConfiguration::Attributes* pAttributes = reinterpret_cast<MenuConfiguration::Attributes *>(nAttributePtr);
+ if (pAttributes)
+ aImageId = pAttributes->aImageId;
if ( !aImageId.isEmpty() )
{
@@ -345,13 +346,12 @@ void NewMenuController::fillPopupMenu( Reference< css::awt::XPopupMenu >& rPopup
if (( nItemId != 0 ) &&
( pSubMenu->GetItemType( nItemId ) != MenuItemType::SEPARATOR ))
{
- MenuConfiguration::Attributes* pBmkAttributes = reinterpret_cast<MenuConfiguration::Attributes *>(pSubMenu->GetUserValue( nItemId ));
- if ( pBmkAttributes != 0 )
+ sal_uIntPtr nAttributePtr = pSubMenu->GetUserValue(nItemId);
+ if (nAttributePtr)
{
- auto result = m_aAddInfoForItem.insert(
- std::make_pair(nItemId, std::unique_ptr<AddInfo>(new AddInfo(*pBmkAttributes))));
- MenuConfiguration::Attributes *pNewInfo = result.first->second.get();
- pVCLPopupMenu->SetUserValue(nItemId, reinterpret_cast<sal_uIntPtr>(pNewInfo));
+ MenuConfiguration::Attributes* pAttributes = reinterpret_cast<MenuConfiguration::Attributes *>(nAttributePtr);
+ pAttributes->acquire();
+ pVCLPopupMenu->SetUserValue(nItemId, nAttributePtr, MenuConfiguration::Attributes::ReleaseAttribute);
}
}
}
@@ -405,10 +405,16 @@ void SAL_CALL NewMenuController::itemSelected( const css::awt::MenuEvent& rEvent
VCLXPopupMenu* pPopupMenu = static_cast<VCLXPopupMenu *>(VCLXPopupMenu::GetImplementation( xPopupMenu ));
if ( pPopupMenu )
{
+ OUString aTargetFrame( m_aTargetFrame );
+
{
SolarMutexGuard aSolarMutexGuard;
PopupMenu* pVCLPopupMenu = static_cast<PopupMenu *>(pPopupMenu->GetMenu());
- aTargetURL.Complete = pVCLPopupMenu->GetItemCommand( rEvent.MenuId );
+ aTargetURL.Complete = pVCLPopupMenu->GetItemCommand(rEvent.MenuId);
+ sal_uIntPtr nAttributePtr = pVCLPopupMenu->GetUserValue(rEvent.MenuId);
+ MenuConfiguration::Attributes* pAttributes = reinterpret_cast<MenuConfiguration::Attributes *>(nAttributePtr);
+ if (pAttributes)
+ aTargetFrame = pAttributes->aTargetFrame;
}
xURLTransformer->parseStrict( aTargetURL );
@@ -416,11 +422,6 @@ void SAL_CALL NewMenuController::itemSelected( const css::awt::MenuEvent& rEvent
aArgsList[0].Name = "Referer";
aArgsList[0].Value = makeAny( OUString( "private:user" ));
- OUString aTargetFrame( m_aTargetFrame );
- AddInfoForId::const_iterator pItem = m_aAddInfoForItem.find( rEvent.MenuId );
- if ( pItem != m_aAddInfoForItem.end() )
- aTargetFrame = pItem->second->aTargetFrame;
-
xDispatch = xDispatchProvider->queryDispatch( aTargetURL, aTargetFrame, 0 );
}
}
diff --git a/include/framework/menuconfiguration.hxx b/include/framework/menuconfiguration.hxx
index 885baae3cdeb..1a952f7330ce 100644
--- a/include/framework/menuconfiguration.hxx
+++ b/include/framework/menuconfiguration.hxx
@@ -61,22 +61,46 @@ class FWE_DLLPUBLIC MenuConfiguration
public:
struct Attributes
{
- Attributes()
- : nStyle(0)
+ private:
+ oslInterlockedCount refCount;
+
+ Attributes(const OUString& rFrame, const OUString& rImageIdStr)
+ : refCount(0)
+ , aTargetFrame(rFrame)
+ , aImageId(rImageIdStr)
+ , nStyle(0)
{
}
- Attributes( const OUString& aFrame, const OUString& aImageIdStr )
- : aTargetFrame(aFrame)
- , aImageId(aImageIdStr)
+ Attributes(const css::uno::WeakReference<css::frame::XDispatchProvider>& rDispatchProvider)
+ : refCount(0)
+ , xDispatchProvider(rDispatchProvider)
, nStyle(0)
{
}
+ Attributes(const Attributes&); //not-implemented
+
+ public:
OUString aTargetFrame;
OUString aImageId;
- ::com::sun::star::uno::WeakReference< ::com::sun::star::frame::XDispatchProvider > xDispatchProvider;
+ css::uno::WeakReference<css::frame::XDispatchProvider> xDispatchProvider;
sal_Int16 nStyle;
+
+ static sal_uIntPtr CreateAttribute(const OUString& rFrame, const OUString& rImageIdStr);
+ static sal_uIntPtr CreateAttribute(const css::uno::WeakReference<css::frame::XDispatchProvider>& rDispatchProvider);
+ static void ReleaseAttribute(sal_uIntPtr nAttributePtr);
+
+ void acquire()
+ {
+ osl_atomic_increment(&refCount);
+ }
+
+ void release()
+ {
+ if (!osl_atomic_decrement(&refCount))
+ delete this;
+ }
};
MenuConfiguration(
diff --git a/include/vcl/menu.hxx b/include/vcl/menu.hxx
index 9466443c37d2..95bf37fe0322 100644
--- a/include/vcl/menu.hxx
+++ b/include/vcl/menu.hxx
@@ -108,6 +108,8 @@ struct MenuLogo
Color aEndColor;
};
+typedef void (*MenuUserDataReleaseFunction)(sal_uLong);
+
class VCL_DLLPUBLIC Menu : public Resource
{
friend class MenuBar;
@@ -263,8 +265,8 @@ public:
void SetItemBits( sal_uInt16 nItemId, MenuItemBits nBits );
MenuItemBits GetItemBits( sal_uInt16 nItemId ) const;
- void SetUserValue( sal_uInt16 nItemId, sal_uLong nValue );
- sal_uLong GetUserValue( sal_uInt16 nItemId ) const;
+ void SetUserValue(sal_uInt16 nItemId, sal_uLong nValue, MenuUserDataReleaseFunction aFunc=0);
+ sal_uLong GetUserValue(sal_uInt16 nItemId) const;
void SetPopupMenu( sal_uInt16 nItemId, PopupMenu* pMenu );
PopupMenu* GetPopupMenu( sal_uInt16 nItemId ) const;
diff --git a/vcl/source/window/menu.cxx b/vcl/source/window/menu.cxx
index 078e1bb31ec9..d08c48a98f4e 100644
--- a/vcl/source/window/menu.cxx
+++ b/vcl/source/window/menu.cxx
@@ -758,11 +758,16 @@ MenuItemBits Menu::GetItemBits( sal_uInt16 nItemId ) const
return nBits;
}
-void Menu::SetUserValue( sal_uInt16 nItemId, sal_uLong nValue )
+void Menu::SetUserValue(sal_uInt16 nItemId, sal_uLong nValue, MenuUserDataReleaseFunction aFunc)
{
- MenuItemData* pData = pItemList->GetData( nItemId );
- if ( pData )
+ MenuItemData* pData = pItemList->GetData(nItemId);
+ if (pData)
+ {
+ if (pData->aUserValueReleaseFunc)
+ pData->aUserValueReleaseFunc(pData->nUserValue);
+ pData->aUserValueReleaseFunc = aFunc;
pData->nUserValue = nValue;
+ }
}
sal_uLong Menu::GetUserValue( sal_uInt16 nItemId ) const
diff --git a/vcl/source/window/menuitemlist.cxx b/vcl/source/window/menuitemlist.cxx
index d6b680adf6dd..c104ba8a1ef8 100644
--- a/vcl/source/window/menuitemlist.cxx
+++ b/vcl/source/window/menuitemlist.cxx
@@ -32,6 +32,8 @@ using namespace vcl;
MenuItemData::~MenuItemData()
{
+ if (aUserValueReleaseFunc)
+ aUserValueReleaseFunc(nUserValue);
if( pAutoSubMenu )
{
static_cast<PopupMenu*>(pAutoSubMenu)->pRefAutoSubMenu = NULL;
diff --git a/vcl/source/window/menuitemlist.hxx b/vcl/source/window/menuitemlist.hxx
index 619e3eb89f00..699ece3e646c 100644
--- a/vcl/source/window/menuitemlist.hxx
+++ b/vcl/source/window/menuitemlist.hxx
@@ -42,7 +42,8 @@ struct MenuItemData
OUString aHelpCommandStr; // Help command string (to reference external help)
OString sIdent;
OString aHelpId; // Help-Id
- sal_uLong nUserValue; // User value
+ sal_uLong nUserValue; // User value
+ MenuUserDataReleaseFunction aUserValueReleaseFunc; // called when MenuItemData is destroyed
Image aImage; // Image
vcl::KeyCode aAccelKey; // Accelerator-Key
bool bChecked; // Checked
@@ -64,6 +65,7 @@ struct MenuItemData
, pSubMenu(NULL)
, pAutoSubMenu(NULL)
, nUserValue(0)
+ , aUserValueReleaseFunc(0)
, bChecked(false)
, bEnabled(false)
, bVisible(false)
@@ -81,6 +83,7 @@ struct MenuItemData
, pAutoSubMenu(NULL)
, aText(rStr)
, nUserValue(0)
+ , aUserValueReleaseFunc(0)
, aImage(rImage)
, bChecked(false)
, bEnabled(false)