diff options
author | Michael Weghorn <m.weghorn@posteo.de> | 2023-12-20 11:12:58 +0100 |
---|---|---|
committer | Michael Weghorn <m.weghorn@posteo.de> | 2023-12-20 17:38:08 +0100 |
commit | 70ef230aae4f961c8197cc11a7ff5feaf1d96c20 (patch) | |
tree | af8f1f6a1fd2397c294422dd009f91bad8c88157 /vcl/unx/gtk4 | |
parent | 552a0a0e4daaac6896995b1ce63a44df6582ade2 (diff) |
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>
Diffstat (limited to 'vcl/unx/gtk4')
-rw-r--r-- | vcl/unx/gtk4/a11y.cxx | 23 | ||||
-rw-r--r-- | vcl/unx/gtk4/a11y.hxx | 15 | ||||
-rw-r--r-- | vcl/unx/gtk4/gtkaccessibleeventlistener.cxx | 7 | ||||
-rw-r--r-- | vcl/unx/gtk4/gtkaccessibleeventlistener.hxx | 2 | ||||
-rw-r--r-- | vcl/unx/gtk4/gtkaccessibleregistry.cxx | 41 | ||||
-rw-r--r-- | vcl/unx/gtk4/gtkaccessibleregistry.hxx | 32 |
6 files changed, 102 insertions, 18 deletions
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: */ |