diff options
author | Michael Weghorn <m.weghorn@posteo.de> | 2024-04-26 09:45:39 +0200 |
---|---|---|
committer | Michael Weghorn <m.weghorn@posteo.de> | 2024-04-26 20:18:15 +0200 |
commit | 707e4f12f11efa3ef575adf549cafb8ecdbfa045 (patch) | |
tree | ea2e1c7fcc6cf1c19f5548050f1ef9a825db285a | |
parent | 59ad8d6d15c893e8873f4afb55a24ab3e58fa2c1 (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.cxx | 10 |
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) |