summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Weghorn <m.weghorn@posteo.de>2023-12-20 11:12:58 +0100
committerMichael Weghorn <m.weghorn@posteo.de>2023-12-20 17:38:08 +0100
commit70ef230aae4f961c8197cc11a7ff5feaf1d96c20 (patch)
treeaf8f1f6a1fd2397c294422dd009f91bad8c88157
parentgtk4 a11y: Silence loplugin:unreffun a different way (diff)
downloadcore-70ef230aae4f961c8197cc11a7ff5feaf1d96c20.tar.gz
core-70ef230aae4f961c8197cc11a7ff5feaf1d96c20.zip
gtk4 a11y: Remember LoAccessible for XAccessible
Don't create a new `LoAccessible` for an `XAccessible` each time, but add a `GtkAccessibleRegistry` class that remembers the corresponding `LoAccessible` for an `XAccessible` in a map. Remove the entry from the map again in `GtkAccessibleEventListener::disposing`. This prevents Libreoffice from becoming unresponsive in local WIP branches of both, gtk and LO that add handling for changes to the focused state, when used with the Orca screen reader. This commit is very similar to what was added for the Qt-based VCL plugins in commit 812fe185fba48b439fb1229517d62aa67c209016 Author: Michael Weghorn <m.weghorn@posteo.de> Date: Wed Aug 24 11:42:04 2022 +0200 qt a11y: Remember and reuse existing QObject for XAccessible Change-Id: Ib217b477bf15abf255fcf254bf607ab8fc11a040 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161061 Tested-by: Jenkins Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
-rw-r--r--vcl/Library_vclplug_gtk4.mk1
-rw-r--r--vcl/unx/gtk4/a11y.cxx23
-rw-r--r--vcl/unx/gtk4/a11y.hxx15
-rw-r--r--vcl/unx/gtk4/gtkaccessibleeventlistener.cxx7
-rw-r--r--vcl/unx/gtk4/gtkaccessibleeventlistener.hxx2
-rw-r--r--vcl/unx/gtk4/gtkaccessibleregistry.cxx41
-rw-r--r--vcl/unx/gtk4/gtkaccessibleregistry.hxx32
7 files changed, 103 insertions, 18 deletions
diff --git a/vcl/Library_vclplug_gtk4.mk b/vcl/Library_vclplug_gtk4.mk
index a288e5151aa6..72ffeb08e267 100644
--- a/vcl/Library_vclplug_gtk4.mk
+++ b/vcl/Library_vclplug_gtk4.mk
@@ -89,6 +89,7 @@ $(eval $(call gb_Library_add_exception_objects,vclplug_gtk4,\
vcl/unx/gtk4/convert3to4 \
vcl/unx/gtk4/customcellrenderer \
vcl/unx/gtk4/gtkaccessibleeventlistener \
+ vcl/unx/gtk4/gtkaccessibleregistry \
vcl/unx/gtk4/gtkdata \
vcl/unx/gtk4/gtkinst \
vcl/unx/gtk4/gtksys \
diff --git a/vcl/unx/gtk4/a11y.cxx b/vcl/unx/gtk4/a11y.cxx
index 4107c7ff0b79..48c22beb21ee 100644
--- a/vcl/unx/gtk4/a11y.cxx
+++ b/vcl/unx/gtk4/a11y.cxx
@@ -22,6 +22,7 @@
#include "a11y.hxx"
#include "gtkaccessibleeventlistener.hxx"
+#include "gtkaccessibleregistry.hxx"
#define OOO_TYPE_FIXED (ooo_fixed_get_type())
#define OOO_FIXED(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), OOO_TYPE_FIXED, OOoFixed))
@@ -383,15 +384,6 @@ applyObjectAttributes(GtkAccessible* pGtkAccessible,
#define LO_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), LO_TYPE_ACCESSIBLE, LoAccessible))
// #define LO_IS_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LO_TYPE_ACCESSIBLE))
-struct LoAccessible
-{
- GObject parent_instance;
- GdkDisplay* display;
- GtkAccessible* parent;
- GtkATContext* at_context;
- css::uno::Reference<css::accessibility::XAccessible> uno_accessible;
-};
-
struct LoAccessibleClass
{
GObjectClass parent_class;
@@ -590,7 +582,7 @@ static void lo_accessible_class_init(LoAccessibleClass* klass)
g_object_class_override_property(object_class, PROP_ACCESSIBLE_ROLE, "accessible-role");
}
-static LoAccessible*
+LoAccessible*
lo_accessible_new(GdkDisplay* pDisplay, GtkAccessible* pParent,
const css::uno::Reference<css::accessibility::XAccessible>& rAccessible)
{
@@ -684,7 +676,8 @@ static GtkAccessible* lo_accessible_get_first_accessible_child(GtkAccessible* se
if (!xFirstChild)
return nullptr;
- LoAccessible* child_accessible = lo_accessible_new(pAccessible->display, self, xFirstChild);
+ LoAccessible* child_accessible
+ = GtkAccessibleRegistry::getLOAccessible(xFirstChild, pAccessible->display, self);
return GTK_ACCESSIBLE(g_object_ref(child_accessible));
}
@@ -711,8 +704,8 @@ static GtkAccessible* lo_accessible_get_next_accessible_sibling(GtkAccessible* s
if (!xNextChild)
return nullptr;
- LoAccessible* child_accessible
- = lo_accessible_new(pAccessible->display, pAccessible->parent, xNextChild);
+ LoAccessible* child_accessible = GtkAccessibleRegistry::getLOAccessible(
+ xNextChild, pAccessible->display, pAccessible->parent);
return GTK_ACCESSIBLE(g_object_ref(child_accessible));
}
@@ -846,8 +839,8 @@ static GtkAccessible* get_first_accessible_child(GtkAccessible* accessible)
return nullptr;
css::uno::Reference<css::accessibility::XAccessible> xFirstChild(
xContext->getAccessibleChild(0));
- LoAccessible* child_accessible
- = lo_accessible_new(gtk_widget_get_display(GTK_WIDGET(pFixed)), accessible, xFirstChild);
+ LoAccessible* child_accessible = GtkAccessibleRegistry::getLOAccessible(
+ xFirstChild, gtk_widget_get_display(GTK_WIDGET(pFixed)), accessible);
return GTK_ACCESSIBLE(g_object_ref(child_accessible));
}
diff --git a/vcl/unx/gtk4/a11y.hxx b/vcl/unx/gtk4/a11y.hxx
index 3b2e9ce02714..7fc0b2acdab9 100644
--- a/vcl/unx/gtk4/a11y.hxx
+++ b/vcl/unx/gtk4/a11y.hxx
@@ -10,13 +10,26 @@
#pragma once
#include <gtk/gtk.h>
+#include <com/sun/star/accessibility/XAccessible.hpp>
//TODO: Silence various loplugin:external and loplugin:unreffun in (WIP?) a11y.cxx for now:
-struct LoAccessible;
struct LoAccessibleClass;
struct OOoFixed;
struct OOoFixedClass;
GType lo_accessible_get_type();
GtkWidget* ooo_fixed_new();
+struct LoAccessible
+{
+ GObject parent_instance;
+ GdkDisplay* display;
+ GtkAccessible* parent;
+ GtkATContext* at_context;
+ css::uno::Reference<css::accessibility::XAccessible> uno_accessible;
+};
+
+LoAccessible*
+lo_accessible_new(GdkDisplay* pDisplay, GtkAccessible* pParent,
+ const css::uno::Reference<css::accessibility::XAccessible>& rAccessible);
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/vcl/unx/gtk4/gtkaccessibleeventlistener.cxx b/vcl/unx/gtk4/gtkaccessibleeventlistener.cxx
index 1bfa69530be3..256073805e7c 100644
--- a/vcl/unx/gtk4/gtkaccessibleeventlistener.cxx
+++ b/vcl/unx/gtk4/gtkaccessibleeventlistener.cxx
@@ -12,6 +12,7 @@
#include <sal/log.hxx>
#include "gtkaccessibleeventlistener.hxx"
+#include "gtkaccessibleregistry.hxx"
GtkAccessibleEventListener::GtkAccessibleEventListener(LoAccessible* pLoAccessible)
: m_pLoAccessible(pLoAccessible)
@@ -26,7 +27,11 @@ GtkAccessibleEventListener::~GtkAccessibleEventListener()
g_object_unref(m_pLoAccessible);
}
-void GtkAccessibleEventListener::disposing(const com::sun::star::lang::EventObject&) {}
+void GtkAccessibleEventListener::disposing(const com::sun::star::lang::EventObject&)
+{
+ assert(m_pLoAccessible);
+ GtkAccessibleRegistry::remove(m_pLoAccessible->uno_accessible);
+}
void GtkAccessibleEventListener::notifyEvent(
const com::sun::star::accessibility::AccessibleEventObject& rEvent)
diff --git a/vcl/unx/gtk4/gtkaccessibleeventlistener.hxx b/vcl/unx/gtk4/gtkaccessibleeventlistener.hxx
index 584cacff85fa..4422156d6c3b 100644
--- a/vcl/unx/gtk4/gtkaccessibleeventlistener.hxx
+++ b/vcl/unx/gtk4/gtkaccessibleeventlistener.hxx
@@ -15,7 +15,7 @@
#include <com/sun/star/lang/EventObject.hpp>
#include <cppuhelper/implbase.hxx>
-struct LoAccessible;
+#include "a11y.hxx"
class GtkAccessibleEventListener final
: public cppu::WeakImplHelper<css::accessibility::XAccessibleEventListener>
diff --git a/vcl/unx/gtk4/gtkaccessibleregistry.cxx b/vcl/unx/gtk4/gtkaccessibleregistry.cxx
new file mode 100644
index 000000000000..3f5df43ed40e
--- /dev/null
+++ b/vcl/unx/gtk4/gtkaccessibleregistry.cxx
@@ -0,0 +1,41 @@
+/* -*- 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/.
+ */
+
+#include "gtkaccessibleregistry.hxx"
+#include "a11y.hxx"
+
+#include <cassert>
+
+std::map<css::accessibility::XAccessible*, LoAccessible*> GtkAccessibleRegistry::m_aMapping = {};
+
+LoAccessible*
+GtkAccessibleRegistry::getLOAccessible(css::uno::Reference<css::accessibility::XAccessible> xAcc,
+ GdkDisplay* pDisplay, GtkAccessible* pParent)
+{
+ if (!xAcc.is())
+ return nullptr;
+
+ // look for existing entry in the map
+ auto entry = m_aMapping.find(xAcc.get());
+ if (entry != m_aMapping.end())
+ return entry->second;
+
+ // create a new object and remember it in the map
+ LoAccessible* pLoAccessible = lo_accessible_new(pDisplay, pParent, xAcc);
+ m_aMapping.emplace(xAcc.get(), pLoAccessible);
+ return pLoAccessible;
+}
+
+void GtkAccessibleRegistry::remove(css::uno::Reference<css::accessibility::XAccessible> xAcc)
+{
+ assert(xAcc.is());
+ m_aMapping.erase(xAcc.get());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk4/gtkaccessibleregistry.hxx b/vcl/unx/gtk4/gtkaccessibleregistry.hxx
new file mode 100644
index 000000000000..390b60c4345d
--- /dev/null
+++ b/vcl/unx/gtk4/gtkaccessibleregistry.hxx
@@ -0,0 +1,32 @@
+/* -*- 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/.
+ */
+
+#pragma once
+
+#include <map>
+#include <gtk/gtk.h>
+#include <com/sun/star/accessibility/XAccessible.hpp>
+
+struct LoAccessible;
+
+class GtkAccessibleRegistry
+{
+private:
+ static std::map<css::accessibility::XAccessible*, LoAccessible*> m_aMapping;
+ GtkAccessibleRegistry() = delete;
+
+public:
+ /** Returns the related LoAccessible* for the XAccessible. Creates a new one if none exists yet. */
+ static LoAccessible* getLOAccessible(css::uno::Reference<css::accessibility::XAccessible> xAcc,
+ GdkDisplay* pDisplay, GtkAccessible* pParent);
+ /** Removes the entry for the given XAccessible. */
+ static void remove(css::uno::Reference<css::accessibility::XAccessible> xAcc);
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */