tdf#119388 add new UNO listener/broadcaster
so that we only need to fire each event to the exact shape that wants
it, instead of spamming all the shapes.
Takes deleting a column from 20s to 10s for me.
Note that none of the broadcasters are calling disposing(EventObject),
so I did not make XShapeEventListener extend lang::XEventListener.
If a memory leak regression points at this commit, possibly I
missed something.
Change-Id: I2b8db08247d3e0203d41faf77491368168994e4d
Reviewed-on: https://gerrit.libreoffice.org/77857
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
diff --git a/include/sfx2/sfxbasemodel.hxx b/include/sfx2/sfxbasemodel.hxx
index 9dcba7e..92c69b5 100644
--- a/include/sfx2/sfxbasemodel.hxx
+++ b/include/sfx2/sfxbasemodel.hxx
@@ -34,6 +34,7 @@
#include <com/sun/star/document/XUndoManagerSupplier.hpp>
#include <com/sun/star/rdf/XDocumentMetadataAccess.hpp>
#include <com/sun/star/document/XEventBroadcaster.hpp>
#include <com/sun/star/document/XShapeEventBroadcaster.hpp>
#include <com/sun/star/document/XDocumentEventBroadcaster.hpp>
#include <com/sun/star/document/XEventsSupplier.hpp>
#include <com/sun/star/document/XEmbeddedScripts.hpp>
@@ -119,7 +120,7 @@ typedef ::cppu::WeakImplHelper < css::container::XChild
, css::rdf::XDocumentMetadataAccess
, css::document::XDocumentRecovery
, css::document::XUndoManagerSupplier
, css::document::XEventBroadcaster
, css::document::XShapeEventBroadcaster
, css::document::XDocumentEventBroadcaster
, css::lang::XEventListener
, css::document::XEventsSupplier
@@ -494,24 +495,33 @@ public:
virtual css::uno::Reference< css::document::XEmbeddedScripts > SAL_CALL getScriptContainer() override;
// XEventBroadcaster
// document::XEventBroadcaster
/**___________________________________________________________________________________________________
@descr - registers the given XEventListener.
*/
virtual void SAL_CALL addEventListener( const css::uno::Reference< css::document::XEventListener >& xListener ) override;
/**___________________________________________________________________________________________________
@descr - unregisters the given XEventListener.
*/
virtual void SAL_CALL removeEventListener( const css::uno::Reference< css::document::XEventListener >& xListener ) override;
// XDocumentEventBroadcaster
// document::XShapeEventBroadcaster
/**___________________________________________________________________________________________________
@descr - registers the given XEventListener.
*/
virtual void SAL_CALL addShapeEventListener( const css::uno::Reference< css::drawing::XShape >& xShape, const css::uno::Reference< css::document::XShapeEventListener >& xListener ) override;
/**___________________________________________________________________________________________________
@descr - unregisters the given XEventListener.
*/
virtual void SAL_CALL removeShapeEventListener( const css::uno::Reference< css::drawing::XShape >& xShape, const css::uno::Reference< css::document::XShapeEventListener >& xListener ) override;
// XDocumentEventBroadcaster
virtual void SAL_CALL addDocumentEventListener( const css::uno::Reference< css::document::XDocumentEventListener >& Listener ) override;
virtual void SAL_CALL removeDocumentEventListener( const css::uno::Reference< css::document::XDocumentEventListener >& Listener ) override;
diff --git a/include/svx/AccessibleControlShape.hxx b/include/svx/AccessibleControlShape.hxx
index 2ea2f73..9b7ff79 100644
--- a/include/svx/AccessibleControlShape.hxx
+++ b/include/svx/AccessibleControlShape.hxx
@@ -114,9 +114,6 @@ private:
//--- XAccessibleEventListener ----------------------------
virtual void SAL_CALL notifyEvent( const css::accessibility::AccessibleEventObject& aEvent ) override;
//--- document::XEventListener ----------------------------
using AccessibleShape::notifyEvent;
// XVclContainerListener
virtual void SAL_CALL elementInserted( const css::container::ContainerEvent& Event ) override;
virtual void SAL_CALL elementRemoved( const css::container::ContainerEvent& Event ) override;
diff --git a/include/svx/AccessibleShape.hxx b/include/svx/AccessibleShape.hxx
index 7d182e5..a70f95e 100644
--- a/include/svx/AccessibleShape.hxx
+++ b/include/svx/AccessibleShape.hxx
@@ -29,7 +29,7 @@
#include <com/sun/star/awt/Point.hpp>
#include <com/sun/star/awt/Rectangle.hpp>
#include <com/sun/star/awt/Size.hpp>
#include <com/sun/star/document/XEventListener.hpp>
#include <com/sun/star/document/XShapeEventListener.hpp>
#include <com/sun/star/lang/EventObject.hpp>
#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/uno/Reference.hxx>
@@ -99,7 +99,7 @@ class SVX_DLLPUBLIC AccessibleShape
public css::accessibility::XAccessibleGroupPosition,
public css::accessibility::XAccessibleHypertext,
public IAccessibleViewForwarderListener,
public css::document::XEventListener,
public css::document::XShapeEventListener,
public css::lang::XUnoTunnel
{
public:
@@ -312,18 +312,15 @@ public:
//===== IAccessibleViewForwarderListener ================================
virtual void ViewForwarderChanged() override;
//===== lang::XEventListener ============================================
/** Listen for disposing events of the model. The accessible shape
remains functional when this happens.
*/
virtual void SAL_CALL
disposing (const css::lang::EventObject& Source) override;
void disposing (const css::lang::EventObject& Source);
//===== document::XEventListener ========================================
//===== document::XShapeEventListener ========================================
virtual void SAL_CALL
notifyEvent (const css::document::EventObject& rEventObject) override;
notifyShapeEvent (const css::document::EventObject& rEventObject) override;
//===== XUnoTunnel ========================================================
diff --git a/include/svx/AccessibleShapeTreeInfo.hxx b/include/svx/AccessibleShapeTreeInfo.hxx
index 0b5ddf8..82f9875 100644
--- a/include/svx/AccessibleShapeTreeInfo.hxx
+++ b/include/svx/AccessibleShapeTreeInfo.hxx
@@ -26,7 +26,7 @@
namespace com { namespace sun { namespace star {
namespace accessibility { class XAccessibleComponent; }
namespace document { class XEventBroadcaster; }
namespace document { class XShapeEventBroadcaster; }
namespace frame { class XController; }
} } }
@@ -89,7 +89,7 @@ public:
reference may be passed to unset the broadcaster
*/
void SetModelBroadcaster (const css::uno::Reference<
css::document::XEventBroadcaster>& rxModelBroadcaster);
css::document::XShapeEventBroadcaster>& rxModelBroadcaster);
/** Return the current model broadcaster.
@return
@@ -97,7 +97,7 @@ public:
been set or has been set to an empty reference.
*/
const css::uno::Reference<
css::document::XEventBroadcaster>&
css::document::XShapeEventBroadcaster>&
GetModelBroadcaster() const { return mxModelBroadcaster;}
/** Set the view that will be used to construct SvxTextEditSources which
@@ -173,7 +173,7 @@ private:
This once was named mxControllerBroadcaster.
*/
css::uno::Reference<
css::document::XEventBroadcaster> mxModelBroadcaster;
css::document::XShapeEventBroadcaster> mxModelBroadcaster;
/** This view is necessary to construct an SvxTextEditSource which in
turn is used to create an accessible edit engine.
diff --git a/offapi/UnoApi_offapi.mk b/offapi/UnoApi_offapi.mk
index 59d7e167..474fc58 100644
--- a/offapi/UnoApi_offapi.mk
+++ b/offapi/UnoApi_offapi.mk
@@ -2246,6 +2246,8 @@ $(eval $(call gb_UnoApi_add_idlfiles,offapi,com/sun/star/document,\
XOOXMLDocumentPropertiesImporter \
XRedlinesSupplier \
XScriptInvocationContext \
XShapeEventBroadcaster \
XShapeEventListener \
XStorageBasedDocument \
XStorageChangeListener \
XTypeDetection \
diff --git a/offapi/com/sun/star/document/XShapeEventBroadcaster.idl b/offapi/com/sun/star/document/XShapeEventBroadcaster.idl
new file mode 100644
index 0000000..52e49ec
--- /dev/null
+++ b/offapi/com/sun/star/document/XShapeEventBroadcaster.idl
@@ -0,0 +1,55 @@
/* -*- 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 __com_sun_star_document_XShapeEventBroadcaster_idl__
#define __com_sun_star_document_XShapeEventBroadcaster_idl__
#include <com/sun/star/document/XShapeEventListener.idl>
#include <com/sun/star/drawing/XShape.idl>
module com { module sun { module star { module document {
/**
Used to link a listener to a specific shape
@since LibreOffice 6.4
*/
interface XShapeEventBroadcaster : com::sun::star::document::XEventBroadcaster
{
/** registers the given listener
@param Listener
listener which is interested on such events
*/
void addShapeEventListener( [in] com::sun::star::drawing::XShape Shape, [in] XShapeEventListener Listener );
/** unregisters the given listener
@param Listener
listener which isn't interested on such events any longer
*/
void removeShapeEventListener( [in] com::sun::star::drawing::XShape Shape, [in] XShapeEventListener Listener );
};
}; }; }; };
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/offapi/com/sun/star/document/XShapeEventListener.idl b/offapi/com/sun/star/document/XShapeEventListener.idl
new file mode 100644
index 0000000..56634d1
--- /dev/null
+++ b/offapi/com/sun/star/document/XShapeEventListener.idl
@@ -0,0 +1,49 @@
/* -*- 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 __com_sun_star_document_XShapeEventListener_idl__
#define __com_sun_star_document_XShapeEventListener_idl__
#include <com/sun/star/document/EventObject.idl>
module com { module sun { module star { module document {
/** makes it possible to register listeners, which are called whenever
a document or document content event occurs
<p>Such events will be broadcasted by a XShapeEventBroadcaster.</p>
@since LibreOffice 6.4
*/
interface XShapeEventListener
{
/** is called whenever a document event (see EventObject) occurs
@param Event
specifies the event type
*/
void notifyShapeEvent( [in] EventObject Event );
};
}; }; }; };
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/Accessibility/DrawModelBroadcaster.cxx b/sc/source/ui/Accessibility/DrawModelBroadcaster.cxx
index 4cf1567..5b63c99 100644
--- a/sc/source/ui/Accessibility/DrawModelBroadcaster.cxx
+++ b/sc/source/ui/Accessibility/DrawModelBroadcaster.cxx
@@ -21,6 +21,7 @@
#include <sal/log.hxx>
#include <svx/svdmodel.hxx>
#include <svx/unomod.hxx>
#include <svx/svdobj.hxx>
#include <tools/diagnose_ex.h>
using namespace ::com::sun::star;
@@ -49,6 +50,30 @@ void SAL_CALL ScDrawModelBroadcaster::removeEventListener( const uno::Reference<
maEventListeners.removeInterface( xListener );
}
void SAL_CALL ScDrawModelBroadcaster::addShapeEventListener(
const css::uno::Reference< css::drawing::XShape >& xShape,
const uno::Reference< document::XShapeEventListener >& xListener )
{
osl::MutexGuard aGuard(maListenerMutex);
auto rv = maShapeListeners.emplace(xShape, xListener);
assert(rv.second && "duplicate listener?");
(void)rv;
}
void SAL_CALL ScDrawModelBroadcaster::removeShapeEventListener(
const css::uno::Reference< css::drawing::XShape >& xShape,
const uno::Reference< document::XShapeEventListener >& xListener )
{
osl::MutexGuard aGuard(maListenerMutex);
auto it = maShapeListeners.find(xShape);
if (it != maShapeListeners.end())
{
assert(it->second == xListener && "removing wrong listener?");
(void)xListener;
maShapeListeners.erase(it);
}
}
void ScDrawModelBroadcaster::Notify( SfxBroadcaster&,
const SfxHint& rHint )
{
@@ -73,6 +98,17 @@ void ScDrawModelBroadcaster::Notify( SfxBroadcaster&,
TOOLS_WARN_EXCEPTION("sc.ui", "Runtime exception caught while notifying shape");
}
}
// right now, we're only handling the specific event necessary to fix this performance problem
if (pSdrHint->GetKind() == SdrHintKind::ObjectChange)
{
auto pSdrObject = const_cast<SdrObject*>(pSdrHint->GetObject());
uno::Reference<drawing::XShape> xShape(pSdrObject->getUnoShape(), uno::UNO_QUERY);
osl::MutexGuard aGuard(maListenerMutex);
auto it = maShapeListeners.find(xShape);
if (it != maShapeListeners.end())
it->second->notifyShapeEvent(aEvent);
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/inc/DrawModelBroadcaster.hxx b/sc/source/ui/inc/DrawModelBroadcaster.hxx
index 6a967a0..0d5966b 100644
--- a/sc/source/ui/inc/DrawModelBroadcaster.hxx
+++ b/sc/source/ui/inc/DrawModelBroadcaster.hxx
@@ -24,14 +24,17 @@
#include <comphelper/interfacecontainer3.hxx>
#include <cppuhelper/implbase.hxx>
#include <com/sun/star/document/XEventBroadcaster.hpp>
#include <com/sun/star/document/XShapeEventBroadcaster.hpp>
#include <unordered_map>
class SdrModel;
class ScDrawModelBroadcaster : public SfxListener,
public ::cppu::WeakImplHelper< css::document::XEventBroadcaster >
public ::cppu::WeakImplHelper< css::document::XShapeEventBroadcaster >
{
mutable ::osl::Mutex maListenerMutex;
::comphelper::OInterfaceContainerHelper3<css::document::XEventListener> maEventListeners;
std::unordered_map<css::uno::Reference< css::drawing::XShape >, css::uno::Reference< css::document::XShapeEventListener >> maShapeListeners;
SdrModel *mpDrawModel;
public:
@@ -39,8 +42,12 @@ public:
ScDrawModelBroadcaster( SdrModel *pDrawModel );
virtual ~ScDrawModelBroadcaster() override;
// css::document::XEventBroadcaster
virtual void SAL_CALL addEventListener( const css::uno::Reference< css::document::XEventListener >& xListener ) override;
virtual void SAL_CALL removeEventListener( const css::uno::Reference< css::document::XEventListener >& xListener ) override;
// css::document::XShapeEventBroadcaster
virtual void SAL_CALL addShapeEventListener( const css::uno::Reference< css::drawing::XShape >& xShape, const css::uno::Reference< css::document::XShapeEventListener >& xListener ) override;
virtual void SAL_CALL removeShapeEventListener( const css::uno::Reference< css::drawing::XShape >& xShape, const css::uno::Reference< css::document::XShapeEventListener >& xListener ) override;
virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override;
};
diff --git a/sd/source/ui/accessibility/AccessibleDocumentViewBase.cxx b/sd/source/ui/accessibility/AccessibleDocumentViewBase.cxx
index 1d2d101..fe80803 100644
--- a/sd/source/ui/accessibility/AccessibleDocumentViewBase.cxx
+++ b/sd/source/ui/accessibility/AccessibleDocumentViewBase.cxx
@@ -20,7 +20,7 @@
#include <AccessibleDocumentViewBase.hxx>
#include <com/sun/star/drawing/XDrawView.hpp>
#include <com/sun/star/frame/XController.hpp>
#include <com/sun/star/document/XEventBroadcaster.hpp>
#include <com/sun/star/document/XShapeEventBroadcaster.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/accessibility/AccessibleEventId.hpp>
#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
@@ -76,8 +76,8 @@ AccessibleDocumentViewBase::AccessibleDocumentViewBase (
// Fill the shape tree info.
maShapeTreeInfo.SetModelBroadcaster (
uno::Reference<document::XEventBroadcaster>(
mxModel, uno::UNO_QUERY));
uno::Reference<document::XShapeEventBroadcaster>(
mxModel, uno::UNO_QUERY_THROW));
maShapeTreeInfo.SetController (mxController);
maShapeTreeInfo.SetSdrView (pViewShell->GetView());
maShapeTreeInfo.SetDevice (pSdWindow);
diff --git a/sd/source/ui/accessibility/AccessiblePageShape.cxx b/sd/source/ui/accessibility/AccessiblePageShape.cxx
index 5e22d74..6390ce1 100644
--- a/sd/source/ui/accessibility/AccessiblePageShape.cxx
+++ b/sd/source/ui/accessibility/AccessiblePageShape.cxx
@@ -216,24 +216,10 @@ css::uno::Sequence< OUString> SAL_CALL
return AccessibleShape::getSupportedServiceNames();
}
//===== lang::XEventListener ================================================
void SAL_CALL
AccessiblePageShape::disposing (const css::lang::EventObject& aEvent)
{
ThrowIfDisposed ();
AccessibleShape::disposing (aEvent);
}
//===== XComponent ==========================================================
void AccessiblePageShape::dispose()
{
// Unregister listeners.
Reference<lang::XComponent> xComponent (mxShape, uno::UNO_QUERY);
if (xComponent.is())
xComponent->removeEventListener (this);
// Cleanup.
mxShape = nullptr;
diff --git a/sd/source/ui/inc/AccessiblePageShape.hxx b/sd/source/ui/inc/AccessiblePageShape.hxx
index 71cc0a7..ced504f 100644
--- a/sd/source/ui/inc/AccessiblePageShape.hxx
+++ b/sd/source/ui/inc/AccessiblePageShape.hxx
@@ -95,11 +95,6 @@ public:
virtual css::uno::Sequence< OUString> SAL_CALL
getSupportedServiceNames() override;
//===== lang::XEventListener ============================================
virtual void SAL_CALL
disposing (const css::lang::EventObject& Source) override;
using AccessibleShape::disposing;
protected:
diff --git a/sfx2/source/doc/sfxbasemodel.cxx b/sfx2/source/doc/sfxbasemodel.cxx
index 5c61dfb..19cfb2d 100644
--- a/sfx2/source/doc/sfxbasemodel.cxx
+++ b/sfx2/source/doc/sfxbasemodel.cxx
@@ -198,6 +198,8 @@ struct IMPL_SfxBaseModel_DataContainer : public ::sfx2::IModifiableDocument
OUString m_sRuntimeUID ;
OUString m_aPreusedFilterName ;
::cppu::OMultiTypeInterfaceContainerHelper m_aInterfaceContainer ;
std::unordered_map<css::uno::Reference< css::drawing::XShape >,
css::uno::Reference< css::document::XShapeEventListener >> maShapeListeners;
Reference< XInterface > m_xParent ;
Reference< frame::XController > m_xCurrent ;
Reference< document::XDocumentProperties > m_xDocumentProperties ;
@@ -2370,6 +2372,33 @@ void SAL_CALL SfxBaseModel::removeEventListener( const Reference< document::XEve
m_pData->m_aInterfaceContainer.removeInterface( cppu::UnoType<document::XEventListener>::get(), aListener );
}
// XShapeEventBroadcaster
void SAL_CALL SfxBaseModel::addShapeEventListener( const css::uno::Reference< css::drawing::XShape >& xShape, const Reference< document::XShapeEventListener >& xListener )
{
SfxModelGuard aGuard( *this, SfxModelGuard::E_INITIALIZING );
auto rv = m_pData->maShapeListeners.emplace(xShape, xListener);
assert(rv.second && "duplicate listener?");
(void)rv;
}
// XShapeEventBroadcaster
void SAL_CALL SfxBaseModel::removeShapeEventListener( const css::uno::Reference< css::drawing::XShape >& xShape, const Reference< document::XShapeEventListener >& xListener )
{
SfxModelGuard aGuard( *this );
auto it = m_pData->maShapeListeners.find(xShape);
if (it != m_pData->maShapeListeners.end())
{
assert(it->second == xListener && "removing wrong listener?");
(void)xListener;
m_pData->maShapeListeners.erase(it);
}
}
// XDocumentEventBroadcaster
@@ -3219,12 +3248,25 @@ void SfxBaseModel::notifyEvent( const document::EventObject& aEvent ) const
aIt.remove();
}
}
// for right now, we're only doing the event that this particular performance problem needed
if (aEvent.EventName == "ShapeModified")
{
uno::Reference<drawing::XShape> xShape(aEvent.Source, uno::UNO_QUERY);
if (xShape.is())
{
auto it = m_pData->maShapeListeners.find(xShape);
if (it != m_pData->maShapeListeners.end())
it->second->notifyShapeEvent(aEvent);
}
}
}
/** returns true if someone added a XEventListener to this XEventBroadcaster */
bool SfxBaseModel::hasEventListeners() const
{
return !impl_isDisposed() && (nullptr != m_pData->m_aInterfaceContainer.getContainer( cppu::UnoType<document::XEventListener>::get()) );
return !impl_isDisposed()
&& ( (nullptr != m_pData->m_aInterfaceContainer.getContainer( cppu::UnoType<document::XEventListener>::get()) )
|| !m_pData->maShapeListeners.empty());
}
void SAL_CALL SfxBaseModel::addPrintJobListener( const Reference< view::XPrintJobListener >& xListener )
diff --git a/svx/source/accessibility/AccessibleShape.cxx b/svx/source/accessibility/AccessibleShape.cxx
index 779ad7b..e9966e3 100644
--- a/svx/source/accessibility/AccessibleShape.cxx
+++ b/svx/source/accessibility/AccessibleShape.cxx
@@ -30,7 +30,7 @@
#include <com/sun/star/container/XChild.hpp>
#include <com/sun/star/drawing/XShapes.hpp>
#include <com/sun/star/drawing/XShapeDescriptor.hpp>
#include <com/sun/star/document/XEventBroadcaster.hpp>
#include <com/sun/star/document/XShapeEventBroadcaster.hpp>
#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
#include <com/sun/star/drawing/FillStyle.hpp>
#include <com/sun/star/text/XText.hpp>
@@ -141,8 +141,8 @@ void AccessibleShape::Init()
// Register at model as document::XEventListener.
if (maShapeTreeInfo.GetModelBroadcaster().is())
maShapeTreeInfo.GetModelBroadcaster()->addEventListener (
static_cast<document::XEventListener*>(this));
maShapeTreeInfo.GetModelBroadcaster()->addShapeEventListener(mxShape,
static_cast<document::XShapeEventListener*>(this));
// Beware! Here we leave the paths of the UNO API and descend into the
// depths of the core. Necessary for making the edit engine
@@ -750,8 +750,7 @@ css::uno::Any SAL_CALL
static_cast<XAccessibleExtendedComponent*>(this),
static_cast< css::accessibility::XAccessibleSelection* >(this),
static_cast< css::accessibility::XAccessibleExtendedAttributes* >(this),
static_cast<lang::XEventListener*>(this),
static_cast<document::XEventListener*>(this),
static_cast<document::XShapeEventListener*>(this),
static_cast<lang::XUnoTunnel*>(this),
static_cast<XAccessibleGroupPosition*>(this),
static_cast<XAccessibleHypertext*>(this)
@@ -937,8 +936,7 @@ uno::Sequence<uno::Type> SAL_CALL
reference to the model in the shape tree info. Otherwise this object
remains functional.
*/
void SAL_CALL
AccessibleShape::disposing (const lang::EventObject& aEvent)
void AccessibleShape::disposing (const lang::EventObject& aEvent)
{
SolarMutexGuard aSolarGuard;
::osl::MutexGuard aGuard (maMutex);
@@ -959,33 +957,27 @@ void SAL_CALL
}
}
// document::XEventListener
// document::XShapeEventListener
void SAL_CALL
AccessibleShape::notifyEvent (const document::EventObject& rEventObject)
AccessibleShape::notifyShapeEvent (const document::EventObject& rEventObject)
{
// First check if the event is for us.
uno::Reference<drawing::XShape> xShape (
rEventObject.Source, uno::UNO_QUERY);
if ( xShape.get() == mxShape.get() )
if (rEventObject.EventName == "ShapeModified")
{
if (rEventObject.EventName == "ShapeModified")
{
//Need to update text children when receiving ShapeModified hint when exiting edit mode for text box
if (mpText)
mpText->UpdateChildren();
//Need to update text children when receiving ShapeModified hint when exiting edit mode for text box
if (mpText)
mpText->UpdateChildren();
// Some property of a shape has been modified. Send an event
// that indicates a change of the visible data to all listeners.
CommitChange (
AccessibleEventId::VISIBLE_DATA_CHANGED,
uno::Any(),
uno::Any());
// Some property of a shape has been modified. Send an event
// that indicates a change of the visible data to all listeners.
CommitChange (
AccessibleEventId::VISIBLE_DATA_CHANGED,
uno::Any(),
uno::Any());
// Name and Description may have changed. Update the local
// values accordingly.
UpdateNameAndDescription();
}
// Name and Description may have changed. Update the local
// values accordingly.
UpdateNameAndDescription();
}
}
@@ -1071,15 +1063,10 @@ void AccessibleShape::disposing()
if (pStateSet != nullptr)
pStateSet->RemoveState (AccessibleStateType::FOCUSED);
// Unregister from broadcasters.
Reference<lang::XComponent> xComponent (mxShape, uno::UNO_QUERY);
if (xComponent.is())
xComponent->removeEventListener (this);
// Unregister from model.
if (maShapeTreeInfo.GetModelBroadcaster().is())
maShapeTreeInfo.GetModelBroadcaster()->removeEventListener (
static_cast<document::XEventListener*>(this));
maShapeTreeInfo.GetModelBroadcaster()->removeShapeEventListener(mxShape,
static_cast<document::XShapeEventListener*>(this));
// Release the child containers.
if (mpChildrenManager != nullptr)
diff --git a/svx/source/accessibility/AccessibleShapeTreeInfo.cxx b/svx/source/accessibility/AccessibleShapeTreeInfo.cxx
index 88d24ac..edc7ef8 100644
--- a/svx/source/accessibility/AccessibleShapeTreeInfo.cxx
+++ b/svx/source/accessibility/AccessibleShapeTreeInfo.cxx
@@ -86,7 +86,7 @@ void AccessibleShapeTreeInfo::SetDocumentWindow (
}
void AccessibleShapeTreeInfo::SetModelBroadcaster (
const Reference<document::XEventBroadcaster>& rxModelBroadcaster)
const Reference<document::XShapeEventBroadcaster>& rxModelBroadcaster)
{
mxModelBroadcaster = rxModelBroadcaster;
}
diff --git a/svx/source/accessibility/ChildrenManagerImpl.cxx b/svx/source/accessibility/ChildrenManagerImpl.cxx
index e08a5c2..2c0b953 100644
--- a/svx/source/accessibility/ChildrenManagerImpl.cxx
+++ b/svx/source/accessibility/ChildrenManagerImpl.cxx
@@ -31,7 +31,7 @@
#include <com/sun/star/accessibility/AccessibleStateType.hpp>
#include <com/sun/star/accessibility/AccessibleEventId.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/document/XEventBroadcaster.hpp>
#include <com/sun/star/document/XShapeEventBroadcaster.hpp>
#include <com/sun/star/frame/XController.hpp>
#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
#include <com/sun/star/view/XSelectionSupplier.hpp>
diff --git a/sw/source/core/access/accmap.cxx b/sw/source/core/access/accmap.cxx
index cb5709c..b5f2c61 100644
--- a/sw/source/core/access/accmap.cxx
+++ b/sw/source/core/access/accmap.cxx
@@ -62,7 +62,7 @@
#include <com/sun/star/accessibility/AccessibleStateType.hpp>
#include <com/sun/star/accessibility/AccessibleRole.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/document/XEventBroadcaster.hpp>
#include <com/sun/star/document/XShapeEventBroadcaster.hpp>
#include <cppuhelper/implbase.hxx>
#include <comphelper/interfacecontainer2.hxx>
#include <pagepreviewlayout.hxx>
@@ -126,10 +126,11 @@ public:
};
class SwDrawModellListener_Impl : public SfxListener,
public ::cppu::WeakImplHelper< document::XEventBroadcaster >
public ::cppu::WeakImplHelper< document::XShapeEventBroadcaster >
{
mutable ::osl::Mutex maListenerMutex;
::comphelper::OInterfaceContainerHelper2 maEventListeners;
std::unordered_map<css::uno::Reference< css::drawing::XShape >, css::uno::Reference< css::document::XShapeEventListener >> maShapeListeners;
SdrModel *mpDrawModel;
protected:
virtual ~SwDrawModellListener_Impl() override;
@@ -137,8 +138,12 @@ protected:
public:
explicit SwDrawModellListener_Impl( SdrModel *pDrawModel );
// css::document::XEventBroadcaster
virtual void SAL_CALL addEventListener( const uno::Reference< document::XEventListener >& xListener ) override;
virtual void SAL_CALL removeEventListener( const uno::Reference< document::XEventListener >& xListener ) override;
// css::document::XShapeEventBroadcaster
virtual void SAL_CALL addShapeEventListener( const css::uno::Reference< css::drawing::XShape >& xShape, const css::uno::Reference< css::document::XShapeEventListener >& xListener ) override;
virtual void SAL_CALL removeShapeEventListener( const css::uno::Reference< css::drawing::XShape >& xShape, const css::uno::Reference< css::document::XShapeEventListener >& xListener ) override;
virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override;
void Dispose();
@@ -166,6 +171,30 @@ void SAL_CALL SwDrawModellListener_Impl::removeEventListener( const uno::Referen
maEventListeners.removeInterface( xListener );
}
void SAL_CALL SwDrawModellListener_Impl::addShapeEventListener(
const css::uno::Reference< css::drawing::XShape >& xShape,
const uno::Reference< document::XShapeEventListener >& xListener )
{
osl::MutexGuard aGuard(maListenerMutex);
auto rv = maShapeListeners.emplace(xShape, xListener);
assert(rv.second && "duplicate listener?");
(void)rv;
}
void SAL_CALL SwDrawModellListener_Impl::removeShapeEventListener(
const css::uno::Reference< css::drawing::XShape >& xShape,
const uno::Reference< document::XShapeEventListener >& xListener )
{
osl::MutexGuard aGuard(maListenerMutex);
auto it = maShapeListeners.find(xShape);
if (it != maShapeListeners.end())
{
assert(it->second == xListener);
(void)xListener;
maShapeListeners.erase(it);
}
}
void SwDrawModellListener_Impl::Notify( SfxBroadcaster& /*rBC*/,
const SfxHint& rHint )
{
@@ -204,6 +233,17 @@ void SwDrawModellListener_Impl::Notify( SfxBroadcaster& /*rBC*/,
TOOLS_WARN_EXCEPTION("sw.a11y", "Runtime exception caught while notifying shape");
}
}
// right now, we're only handling the specific event necessary to fix this performance problem
if (pSdrHint->GetKind() == SdrHintKind::ObjectChange)
{
auto pSdrObject = const_cast<SdrObject*>(pSdrHint->GetObject());
uno::Reference<drawing::XShape> xShape(pSdrObject->getUnoShape(), uno::UNO_QUERY);
osl::MutexGuard aGuard(maListenerMutex);
auto it = maShapeListeners.find(xShape);
if (it != maShapeListeners.end())
it->second->notifyShapeEvent(aEvent);
}
}
void SwDrawModellListener_Impl::Dispose()
@@ -247,7 +287,7 @@ public:
maInfo.SetSdrView( pMap->GetShell()->GetDrawView() );
maInfo.SetDevice( pMap->GetShell()->GetWin() );
maInfo.SetViewForwarder( pMap );
uno::Reference < document::XEventBroadcaster > xModelBroadcaster =
uno::Reference < document::XShapeEventBroadcaster > xModelBroadcaster =
new SwDrawModellListener_Impl(
pMap->GetShell()->getIDocumentDrawModelAccess().GetOrCreateDrawModel() );
maInfo.SetModelBroadcaster( xModelBroadcaster );