summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/vcl/menu.hxx3
-rw-r--r--include/vcl/vclevent.hxx41
-rw-r--r--vcl/inc/svdata.hxx1
-rw-r--r--vcl/inc/vcleventlisteners.hxx58
-rw-r--r--vcl/inc/window.h1
-rw-r--r--vcl/opengl/salbmp.cxx1
-rw-r--r--vcl/source/app/vclevent.cxx47
-rw-r--r--vcl/source/window/menu.cxx16
-rw-r--r--vcl/unx/gtk/window/gtksalmenu.cxx2
9 files changed, 94 insertions, 76 deletions
diff --git a/include/vcl/menu.hxx b/include/vcl/menu.hxx
index 089cd8b4eb5a..456608261de6 100644
--- a/include/vcl/menu.hxx
+++ b/include/vcl/menu.hxx
@@ -404,7 +404,8 @@ public:
namespace vcl { namespace MenuInvalidator {
-VCL_DLLPUBLIC VclEventListeners2* GetMenuInvalidateListeners();
+VCL_DLLPUBLIC void AddMenuInvalidateListener(const Link<>&);
+VCL_DLLPUBLIC void CallMenuInvalidateListeners(VclSimpleEvent* pEvent);
VCL_DLLPUBLIC void Invalidated();
}}
diff --git a/include/vcl/vclevent.hxx b/include/vcl/vclevent.hxx
index f9e8b51564e0..e564100f9a48 100644
--- a/include/vcl/vclevent.hxx
+++ b/include/vcl/vclevent.hxx
@@ -29,9 +29,6 @@
#include <com/sun/star/uno/Reference.hxx>
-#include <list>
-#include <vector>
-
class Menu;
namespace com { namespace sun { namespace star {
@@ -252,44 +249,6 @@ private:
::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > mxAccessible;
};
-class VCL_DLLPUBLIC VclEventListeners
-{
-public:
- void Call( VclSimpleEvent* pEvent ) const;
- void addListener( const Link<>& rListener );
- void removeListener( const Link<>& rListener );
-private:
- std::vector<Link<>> m_aListeners;
-};
-
-class VCL_DLLPUBLIC VclEventListeners2 : public vcl::DeletionNotifier
-{
- std::list< Link<> > m_aListeners;
-
- struct ListenerIt
- {
- std::list< Link<> >::iterator m_aIt;
- bool m_bWasInvalidated;
-
- ListenerIt(const std::list<Link<>>::iterator& rIt)
- : m_aIt(rIt)
- , m_bWasInvalidated( false )
- {}
- };
-
- std::vector< ListenerIt > m_aIterators;
-
-
-public:
- VclEventListeners2();
- ~VclEventListeners2();
-
- void addListener( const Link<>& );
- void removeListener( const Link<>& );
-
- void callListeners( VclSimpleEvent* );
-};
-
#endif // INCLUDED_VCL_VCLEVENT_HXX
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/svdata.hxx b/vcl/inc/svdata.hxx
index 0d8e02c8e110..e7496aa71d24 100644
--- a/vcl/inc/svdata.hxx
+++ b/vcl/inc/svdata.hxx
@@ -35,6 +35,7 @@
#include "vcl/keycod.hxx"
#include "vcl/svapp.hxx"
#include "vcl/vclevent.hxx"
+#include "vcleventlisteners.hxx"
#include "unotools/options.hxx"
diff --git a/vcl/inc/vcleventlisteners.hxx b/vcl/inc/vcleventlisteners.hxx
new file mode 100644
index 000000000000..8e3b026ca953
--- /dev/null
+++ b/vcl/inc/vcleventlisteners.hxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_VCL_INC_VCLEVENTLISTENERS_HXX
+#define INCLUDED_VCL_INC_VCLEVENTLISTENERS_HXX
+
+#include <tools/link.hxx>
+#include <tools/rtti.hxx>
+#include <vcl/dllapi.h>
+#include <vcl/impdel.hxx>
+#include <vcl/vclptr.hxx>
+#include <vcl/window.hxx>
+
+#include <com/sun/star/uno/Reference.hxx>
+
+#include <vector>
+
+class VCL_DLLPUBLIC VclEventListeners
+{
+public:
+ void Call( VclSimpleEvent* pEvent ) const;
+ void addListener( const Link<>& rListener );
+ void removeListener( const Link<>& rListener );
+private:
+ std::vector<Link<>> m_aListeners;
+};
+
+class VCL_DLLPUBLIC VclEventListeners2 : public vcl::DeletionNotifier
+{
+ std::vector<Link<>> m_aListeners;
+public:
+ VclEventListeners2();
+ ~VclEventListeners2();
+
+ void addListener( const Link<>& );
+ void removeListener( const Link<>& );
+ void callListeners( VclSimpleEvent* );
+};
+
+#endif // INCLUDED_VCL_INC_VCLEVENTLISTENERS_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/window.h b/vcl/inc/window.h
index 2e56cc77e71e..4745bf6a4372 100644
--- a/vcl/inc/window.h
+++ b/vcl/inc/window.h
@@ -37,6 +37,7 @@
#include <vcl/vclevent.hxx>
#include <vcl/vclptr.hxx>
#include <vcl/rendersettings.hxx>
+#include "vcleventlisteners.hxx"
#include <vector>
struct SalPaintEvent;
diff --git a/vcl/opengl/salbmp.cxx b/vcl/opengl/salbmp.cxx
index fefa3817b8b2..05c100058567 100644
--- a/vcl/opengl/salbmp.cxx
+++ b/vcl/opengl/salbmp.cxx
@@ -27,6 +27,7 @@
#include "vcl/salbtype.hxx"
#include "svdata.hxx"
#include "salgdi.hxx"
+#include "vcleventlisteners.hxx"
#include "opengl/zone.hxx"
#include "opengl/program.hxx"
diff --git a/vcl/source/app/vclevent.cxx b/vcl/source/app/vclevent.cxx
index bc3ca538f285..7cb291d95eb5 100644
--- a/vcl/source/app/vclevent.cxx
+++ b/vcl/source/app/vclevent.cxx
@@ -21,6 +21,7 @@
#include "vcl/window.hxx"
#include "svdata.hxx"
+#include "vcleventlisteners.hxx"
#include <com/sun/star/accessibility/XAccessible.hpp>
@@ -94,47 +95,35 @@ VclEventListeners2::~VclEventListeners2()
{
}
-void VclEventListeners2::addListener( const Link<>& i_rLink )
+void VclEventListeners2::addListener( const Link<>& rListener )
{
// ensure uniqueness
- for( std::list< Link<> >::const_iterator it = m_aListeners.begin(); it != m_aListeners.end(); ++it )
- {
- if( *it == i_rLink )
- return;
- }
- m_aListeners.push_back( i_rLink );
+ if (std::find(m_aListeners.begin(), m_aListeners.end(), rListener) == m_aListeners.end())
+ m_aListeners.push_back( rListener );
}
-void VclEventListeners2::removeListener( const Link<>& i_rLink )
+void VclEventListeners2::removeListener( const Link<>& rListener )
{
- size_t n = m_aIterators.size();
- for( size_t i = 0; i < n; i++ )
- {
- if( m_aIterators[i].m_aIt != m_aListeners.end() && *m_aIterators[i].m_aIt == i_rLink )
- {
- m_aIterators[i].m_bWasInvalidated = true;
- ++m_aIterators[i].m_aIt;
- }
- }
- m_aListeners.remove( i_rLink );
+ m_aListeners.erase( std::remove(m_aListeners.begin(), m_aListeners.end(), rListener ), m_aListeners.end() );
}
-void VclEventListeners2::callListeners( VclSimpleEvent* i_pEvent )
+void VclEventListeners2::callListeners( VclSimpleEvent* pEvent )
{
vcl::DeletionListener aDel( this );
- m_aIterators.push_back(ListenerIt(m_aListeners.begin()));
- size_t nIndex = m_aIterators.size() - 1;
- while( ! aDel.isDeleted() && m_aIterators[ nIndex ].m_aIt != m_aListeners.end() )
+ // Copy the list, because this can be destroyed when calling a Link...
+ std::vector<Link<>> aCopy( m_aListeners );
+ std::vector<Link<>>::iterator aIter( aCopy.begin() );
+ std::vector<Link<>>::const_iterator aEnd( aCopy.end() );
+
+ while ( aIter != aEnd && ! aDel.isDeleted() )
{
- m_aIterators[ nIndex ].m_aIt->Call( i_pEvent );
- if( m_aIterators[ nIndex ].m_bWasInvalidated )
- // check if the current element was removed and the iterator increased in the meantime
- m_aIterators[ nIndex ].m_bWasInvalidated = false;
- else
- ++m_aIterators[ nIndex ].m_aIt;
+ Link<> &rLink = *aIter;
+ // check this hasn't been removed in some re-enterancy scenario fdo#47368
+ if( std::find(m_aListeners.begin(), m_aListeners.end(), rLink) != m_aListeners.end() )
+ rLink.Call( pEvent );
+ ++aIter;
}
- m_aIterators.pop_back();
}
diff --git a/vcl/source/window/menu.cxx b/vcl/source/window/menu.cxx
index e49ff60f5ec4..e5acc2eca589 100644
--- a/vcl/source/window/menu.cxx
+++ b/vcl/source/window/menu.cxx
@@ -3240,16 +3240,24 @@ ImplMenuDelData::~ImplMenuDelData()
namespace vcl { namespace MenuInvalidator {
static VclEventListeners2* pMenuInvalidateListeners = NULL;
- VclEventListeners2* GetMenuInvalidateListeners()
+ void AddMenuInvalidateListener(const Link<>& rLink)
{
if(!pMenuInvalidateListeners)
pMenuInvalidateListeners = new VclEventListeners2();
- return pMenuInvalidateListeners;
+ pMenuInvalidateListeners->addListener(rLink);
+ }
+ void CallMenuInvalidateListeners(VclSimpleEvent* pEvent)
+ {
+ if(pMenuInvalidateListeners)
+ pMenuInvalidateListeners->callListeners(pEvent);
}
void Invalidated()
{
- VclSimpleEvent aEvent(0);
- GetMenuInvalidateListeners()->callListeners(&aEvent);
+ if(pMenuInvalidateListeners)
+ {
+ VclSimpleEvent aEvent(0);
+ pMenuInvalidateListeners->callListeners(&aEvent);
+ }
};
} }
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk/window/gtksalmenu.cxx b/vcl/unx/gtk/window/gtksalmenu.cxx
index 0dce1c49baf1..ba2c894a86db 100644
--- a/vcl/unx/gtk/window/gtksalmenu.cxx
+++ b/vcl/unx/gtk/window/gtksalmenu.cxx
@@ -414,7 +414,7 @@ void GtkSalMenu::SetFrame( const SalFrame* pFrame )
{
SolarMutexGuard aGuard;
{
- vcl::MenuInvalidator::GetMenuInvalidateListeners()->addListener(*getRefreshLinkInstance());
+ vcl::MenuInvalidator::AddMenuInvalidateListener(*getRefreshLinkInstance());
}
assert(mbMenuBar);