summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Weghorn <m.weghorn@posteo.de>2024-04-26 09:45:39 +0200
committerMichael Weghorn <m.weghorn@posteo.de>2024-04-26 20:18:15 +0200
commit707e4f12f11efa3ef575adf549cafb8ecdbfa045 (patch)
treeea2e1c7fcc6cf1c19f5548050f1ef9a825db285a
parent59ad8d6d15c893e8873f4afb55a24ab3e58fa2c1 (diff)
gtk4 a11y: Don't create multiple AT contexts for same accessible
In the `GtkAccessibleInterface::get_at_context` implementations, do not create a new `GtkATContext` if the accessible role has changed. This broke the apparent assumption that there's a 1:1 mapping between `GtkAccessible` and `GtkATContext` and resulted in segfaults seen quite often when starting LO Writer with the gtk4 VCL plugin while Accerciser was also running. For me, this was even more reproducible when running in rr (crashed reliably on start). LO has the `AccessibleEventId::ROLE_CHANGED` event type to indicate role changes, but GTK 4 doesn't support changing the initial role any more. Quoting the GtkAccessible doc [1]: > The role cannot be changed after instantiating a > GtkAccessible implementation. And the accessibility section in the GTK 4 doc [2] says: > Each role is part of the widget’s instance, and cannot be changed over > time or as the result of a user action. Roles allows assistive > technology applications to identify a UI control and decide how to > present it to a user; if a part of the application’s UI changes role, > the control needs to be removed and replaced with another one > with the appropriate role. Sample backtrace: Thread 1 received signal SIGSEGV, Segmentation fault. 0x00007f0399aa0636 in get_parent_context_ref (accessible=0x55a141b5a9b0) at ../gtk/a11y/gtkatspicontext.c:462 462 res = gtk_at_spi_root_to_ref (self->root); (rr) bt #0 0x00007f0399aa0636 in get_parent_context_ref (accessible=0x55a141b5a9b0) at ../gtk/a11y/gtkatspicontext.c:462 #1 0x00007f0399aa43ba in gtk_at_spi_context_get_parent_ref (self=0x55a141b615c0) at ../gtk/a11y/gtkatspicontext.c:1956 #2 0x00007f0399a9dc75 in collect_object (self=0x55a1469113a0, builder=0x7fff90e1a220, context=0x55a141b615c0) at ../gtk/a11y/gtkatspicache.c:131 #3 0x00007f0399a9e2f2 in emit_add_accessible (self=0x55a1469113a0, context=0x55a141b615c0) at ../gtk/a11y/gtkatspicache.c:235 #4 0x00007f0399a9eac1 in gtk_at_spi_cache_add_context (self=0x55a1469113a0, context=0x55a141b615c0) at ../gtk/a11y/gtkatspicache.c:436 #5 0x00007f0399aa8152 in on_registration_reply (gobject=0x55a141b62060, result=0x55a14e28a890, user_data=0x55a141b64770) at ../gtk/a11y/gtkatspiroot.c:533 #6 0x00007f039fac8ee3 in () at /lib/x86_64-linux-gnu/libgio-2.0.so.0 #7 0x00007f039fac9b83 in () at /lib/x86_64-linux-gnu/libgio-2.0.so.0 #8 0x00007f039fb269da in () at /lib/x86_64-linux-gnu/libgio-2.0.so.0 #9 0x00007f039fac8ee3 in () at /lib/x86_64-linux-gnu/libgio-2.0.so.0 #10 0x00007f039fac8f1d in () at /lib/x86_64-linux-gnu/libgio-2.0.so.0 #11 0x00007f03a0b110d9 in () at /lib/x86_64-linux-gnu/libglib-2.0.so.0 #12 0x00007f03a0b14317 in () at /lib/x86_64-linux-gnu/libglib-2.0.so.0 #13 0x00007f03a0b14930 in g_main_context_iteration () at /lib/x86_64-linux-gnu/libglib-2.0.so.0 #14 0x00007f039a877d9f in GtkSalData::Yield(bool, bool) (this=0x55a140869000, bWait=true, bHandleAllCurrentEvents=false) at vcl/unx/gtk4/../gtk3/gtkdata.cxx:405 #15 0x00007f039a87dc63 in GtkInstance::DoYield(bool, bool) (this=0x55a140868eb0, bWait=true, bHandleAllCurrentEvents=false) at vcl/unx/gtk4/../gtk3/gtkinst.cxx:435 #16 0x00007f03a539a64c in ImplYield(bool, bool) (i_bWait=true, i_bAllEvents=false) at /home/michi/development/git/libreoffice/vcl/source/app/svapp.cxx:394 #17 0x00007f03a5399f5b in Application::Yield() () at /home/michi/development/git/libreoffice/vcl/source/app/svapp.cxx:482 #18 0x00007f03a5399cf2 in Application::Execute() () at /home/michi/development/git/libreoffice/vcl/source/app/svapp.cxx:369 #19 0x00007f03ae52304c in desktop::Desktop::Main() (this=0x7fff90e1c288) at /home/michi/development/git/libreoffice/desktop/source/app/app.cxx:1615 #20 0x00007f03a53bcfbe in ImplSVMain() () at /home/michi/development/git/libreoffice/vcl/source/app/svmain.cxx:229 #21 0x00007f03a53bf009 in SVMain() () at /home/michi/development/git/libreoffice/vcl/source/app/svmain.cxx:261 #22 0x00007f03ae5a5a73 in soffice_main() () at /home/michi/development/git/libreoffice/desktop/source/app/sofficemain.cxx:93 #23 0x000055a13fefca5d in sal_main () at /home/michi/development/git/libreoffice/desktop/source/app/main.c:51 #24 0x000055a13fefca37 in main (argc=2, argv=0x7fff90e1c498) at /home/michi/development/git/libreoffice/desktop/source/app/main.c:49 From valgrind output: (soffice:972353): Gtk-CRITICAL **: 09:28:48.066: gtk_accessible_get_accessible_parent: assertion 'GTK_IS_ACCESSIBLE (self)' failed (soffice:972353): Gtk-CRITICAL **: 09:28:48.067: gtk_accessible_get_at_context: assertion 'GTK_IS_ACCESSIBLE (self)' failed ==972353== Thread 1: ==972353== Invalid read of size 8 ==972353== at 0x19077636: get_parent_context_ref (gtkatspicontext.c:462) ==972353== by 0x1907B3B9: gtk_at_spi_context_get_parent_ref (gtkatspicontext.c:1956) ==972353== by 0x19074C74: collect_object (gtkatspicache.c:131) ==972353== by 0x190752F1: emit_add_accessible (gtkatspicache.c:235) ==972353== by 0x19075AC0: gtk_at_spi_cache_add_context (gtkatspicache.c:436) ==972353== by 0x1907F151: on_registration_reply (gtkatspiroot.c:533) ==972353== by 0x12E72EE2: ??? (in /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0.7800.4) ==972353== by 0x12E73B82: ??? (in /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0.7800.4) ==972353== by 0x12ED09D9: ??? (in /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0.7800.4) ==972353== by 0x12E72EE2: ??? (in /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0.7800.4) ==972353== by 0x12E72F1C: ??? (in /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0.7800.4) ==972353== by 0x130620D8: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.7800.4) ==972353== Address 0x70 is not stack'd, malloc'd or (recently) free'd ==972353== [1] https://docs.gtk.org/gtk4/iface.Accessible.html [2] https://docs.gtk.org/gtk4/section-accessibility.html Change-Id: I35196ca686e9d56f97bbf884da8b6492358e41fc Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166708 Tested-by: Jenkins Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
-rw-r--r--vcl/unx/gtk4/a11y.cxx10
1 files changed, 4 insertions, 6 deletions
diff --git a/vcl/unx/gtk4/a11y.cxx b/vcl/unx/gtk4/a11y.cxx
index 184f6f3be95a..7574e67f5758 100644
--- a/vcl/unx/gtk4/a11y.cxx
+++ b/vcl/unx/gtk4/a11y.cxx
@@ -528,11 +528,9 @@ static GtkATContext* lo_accessible_get_at_context(GtkAccessible* self)
{
LoAccessible* pAccessible = LO_ACCESSIBLE(self);
- GtkAccessibleRole eRole = map_accessible_role(pAccessible->uno_accessible);
-
- if (!pAccessible->at_context
- || gtk_at_context_get_accessible_role(pAccessible->at_context) != eRole)
+ if (!pAccessible->at_context)
{
+ GtkAccessibleRole eRole = map_accessible_role(pAccessible->uno_accessible);
pAccessible->at_context = gtk_at_context_create(eRole, self, pAccessible->display);
if (!pAccessible->at_context)
return nullptr;
@@ -797,13 +795,13 @@ static GtkATContext* get_at_context(GtkAccessible* self)
css::uno::Reference<css::accessibility::XAccessible> xAccessible(
get_uno_accessible(GTK_WIDGET(pFixed)));
- GtkAccessibleRole eRole = map_accessible_role(xAccessible);
- if (!pFixed->at_context || gtk_at_context_get_accessible_role(pFixed->at_context) != eRole)
+ if (!pFixed->at_context)
{
// if (pFixed->at_context)
// g_clear_object(&pFixed->at_context);
+ GtkAccessibleRole eRole = map_accessible_role(xAccessible);
pFixed->at_context
= gtk_at_context_create(eRole, self, gtk_widget_get_display(GTK_WIDGET(pFixed)));
if (!pFixed->at_context)