[Libreoffice-commits] core.git: include/sfx2 include/svx offapi/com offapi/UnoApi_offapi.mk sc/source sd/source sfx2/source svx/source sw/source

Noel Grandin (via logerrit) logerrit at kemper.freedesktop.org
Fri Aug 23 13:12:30 UTC 2019


 include/sfx2/sfxbasemodel.hxx                             |   22 +++--
 include/svx/AccessibleControlShape.hxx                    |    3 
 include/svx/AccessibleShape.hxx                           |   13 +--
 include/svx/AccessibleShapeTreeInfo.hxx                   |    8 -
 offapi/UnoApi_offapi.mk                                   |    2 
 offapi/com/sun/star/document/XShapeEventBroadcaster.idl   |   55 +++++++++++++
 offapi/com/sun/star/document/XShapeEventListener.idl      |   49 ++++++++++++
 sc/source/ui/Accessibility/DrawModelBroadcaster.cxx       |   36 ++++++++
 sc/source/ui/inc/DrawModelBroadcaster.hxx                 |    9 +-
 sd/source/ui/accessibility/AccessibleDocumentViewBase.cxx |    6 -
 sd/source/ui/accessibility/AccessiblePageShape.cxx        |   14 ---
 sd/source/ui/inc/AccessiblePageShape.hxx                  |    5 -
 sfx2/source/doc/sfxbasemodel.cxx                          |   44 ++++++++++
 svx/source/accessibility/AccessibleShape.cxx              |   57 +++++---------
 svx/source/accessibility/AccessibleShapeTreeInfo.cxx      |    2 
 svx/source/accessibility/ChildrenManagerImpl.cxx          |    2 
 sw/source/core/access/accmap.cxx                          |   46 ++++++++++-
 17 files changed, 288 insertions(+), 85 deletions(-)

New commits:
commit ec940941e0bd7db15c5cf7d43df82226e0d849dc
Author:     Noel Grandin <noel.grandin at collabora.co.uk>
AuthorDate: Tue Aug 20 17:03:13 2019 +0200
Commit:     Noel Grandin <noel.grandin at collabora.co.uk>
CommitDate: Fri Aug 23 15:11:27 2019 +0200

    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 at collabora.co.uk>

diff --git a/include/sfx2/sfxbasemodel.hxx b/include/sfx2/sfxbasemodel.hxx
index 9dcba7e68542..92c69b5c3bc9 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 2ea2f73dd6d7..9b7ff797f96b 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 7d182e58b4c8..a70f95edc086 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 0b5ddf8fae52..82f98759902f 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 59d7e16772c8..474fc58160fa 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 000000000000..52e49ec8e96b
--- /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 000000000000..56634d171845
--- /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 4cf1567856c5..5b63c9926baf 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 6a967a075075..0d5966b864fa 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 1d2d1016b594..fe808039929e 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 5e22d74c1c00..6390ce18e3b5 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 71cc0a769be8..ced504f020d3 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 5c61dfb047fa..19cfb2dd49f3 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 779ad7b4fba3..e9966e3c63ef 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 88d24ac1d86f..edc7ef8a9641 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 e08a5c2b0a6e..2c0b953dc459 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 cb5709c54901..b5f2c615961b 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 );


More information about the Libreoffice-commits mailing list