Accessibility problem with custom GtkWidget

Gabor Karsay <[email protected]> Sun, 13 Jan 2019 15:46:30 +0100
Newsgroups gmane.comp.gnome.accessibility.general
Message-ID <[email protected]>
Hello,

I'm an accessibility newbie asking for some help (a hint would be 
enough) with a custom GtkWidget. As I planned to add some Atspi 
functionality I found out that my widget is "disturbing" 
AtspiEventListener. When there is an AtspiEventListener and I open a 
window with my widget and close it again, the listener emits a couple of 
"g_object_unref: assertion 'G_IS_OBJECT (object)' failed" messages.

So obviously my widget is doing something wrong or probably doesn't do 
something it should do. It's a composite widget: a GtkScrolledWindow 
that is showing a couple of GtkDrawingAreas over each other in a 
GtkOverlay. It looks like this: 
https://gkarsay.github.io/parlatype/reference/PtWaveviewer.html

I'm not asking you to have a look at the widget code itself, just some 
general advice what a custom widget should do. Have you seen something 
like this before?

Just to clarify, I didn't do anything yet to improve accessibility. I 
thought if the subwidgets are accessible, then the whole custom widget 
is accessible.

I wrote a test case with a listener. It's just listening as long as the 
window is open:

--------- test.c -----------

/* Compile:
    gcc -g -o test test.c `pkg-config --libs --cflags gtk+-3.0 atspi-2`
*/


#include <gtk/gtk.h>
#include <atspi/atspi.h>

static void
on_event_cb (AtspiEvent *event,
              void       *user_data)
{
	/* nothing */
}

static void
app_activate (GApplication *app,
               gpointer      user_data)
{
	AtspiEventListener *listener;
	GtkWidget          *window;

	listener = atspi_event_listener_new ((AtspiEventListenerCB) 
on_event_cb, NULL, NULL);
	atspi_event_listener_register (listener, 
"object:state-changed:focused", NULL);

	window = gtk_application_window_new (GTK_APPLICATION (app));
	gtk_window_present (GTK_WINDOW (window));
}

int main(int argc, gchar **argv)
{
	GtkApplication *app;
	gint            status;

	app = gtk_application_new ("org.example.test", G_APPLICATION_FLAGS_NONE);
	g_signal_connect (app, "activate", G_CALLBACK (app_activate), NULL);
	status = g_application_run (G_APPLICATION (app), argc, argv);
	g_object_unref (app);

	return status;
}

----- test.c end ---------------

When I run the test (in Debian stable and unstable), open my widget 
(Parlatype) and close it again, I get this from the test program:

(gdb) bt full
#0  0x00007ffff56de261 in _g_log_abort (breakpoint=breakpoint@entry=1) 
at ././glib/gmessages.c:509
         debugger_present = 1
#1  0x00007ffff56df66d in g_logv (log_domain=0x7ffff5e5e9b6 
"GLib-GObject", log_level=G_LOG_LEVEL_CRITICAL, format=<optimized out>, 
args=args@entry=0x7fffffffdba0) at ././glib/gmessages.c:1318
         domain = 0x0
         data = 0x0
         depth = 1
         log_func = 0x7ffff56df1f0 <g_log_default_handler>
         domain_fatal_mask = <optimized out>
         masquerade_fatal = 0
         test_level = 10
         was_fatal = <optimized out>
         was_recursion = <optimized out>
         msg = 0x555555a4bdb0 "g_object_unref: assertion 'G_IS_OBJECT 
(object)' failed"
         msg_alloc = 0x555555a4bdb0 "g_object_unref: assertion 
'G_IS_OBJECT (object)' failed"
         i = 3
#2  0x00007ffff56df7cf in g_log (log_domain=<optimized out>, 
log_level=<optimized out>, format=<optimized out>) at 
././glib/gmessages.c:1359
         args = {{gp_offset = 40, fp_offset = 48, overflow_arg_area = 
0x7fffffffdc80, reg_save_area = 0x7fffffffdbc0}}
#3  0x00007ffff56aca9b in g_ptr_array_foreach (array=0x5555558f8100, 
func=0x7ffff5e37ae0 <g_object_unref>, user_data=0x0) at 
././glib/garray.c:1502
         i = 2
#4  0x00007ffff56acb30 in ptr_array_free (array=0x5555558f8100, 
flags=FREE_SEGMENT) at ././glib/garray.c:1088
         rarray = 0x5555558f8100
         segment = <optimized out>
#5  0x00007ffff56acba9 in g_ptr_array_free (array=<optimized out>, 
free_segment=free_segment@entry=1) at ././glib/garray.c:1075
         rarray = <optimized out>
         flags = <optimized out>
         __func__ = "g_ptr_array_free"
#6  0x00007ffff5c02395 in atspi_accessible_dispose 
(object=0x5555558201a0 [AtspiAccessible]) at atspi-accessible.c:164
         accessible = 0x5555558201a0 [AtspiAccessible]
         e = {type = 0x7ffff5c14aa2 "object:state-changed:defunct", 
source = 0x5555558201a0 [AtspiAccessible], detail1 = 1, detail2 = 0, 
any_data = {g_type = 24, data = {{v_int = 0, v_uint = 0, v_long = 0, 
v_ulong = 0, v_int64 = 0, v_uint64 = 0, v_float = 0, v_double = 0, 
v_pointer = 0x0}, {v_int = 0, v_uint = 0, v_long = 0, v_ulong = 0, 
v_int64 = 0, v_uint64 = 0, v_float = 0, v_double = 0, v_pointer = 0x0}}}}
         parent = <optimized out>
         i = -1
#7  0x00007ffff5e39648 in g_object_run_dispose (object=0x5555558201a0 
[AtspiAccessible]) at ././gobject/gobject.c:1084
         __func__ = "g_object_run_dispose"
#8  0x00007ffff5c0b3bc in handle_remove_accessible (bus=<optimized out>, 
user_data=<optimized out>, message=<optimized out>) at atspi-misc.c:357
         app = 0x555555a2a250 [AtspiApplication]
         iter = {dummy1 = 0x5555558dd840, dummy2 = 0x7fff00600000, 
dummy3 = 108, dummy4 = 0, dummy5 = 1435359304, dummy6 = 21845, dummy7 = 
117, dummy8 = 0, dummy9 = 1435359376, dummy10 = 21845, dummy11 = 0, pad1 
= 0, pad2 = 0x7ffff5befea0, pad3 = 0x0}
         a = 0x5555558201a0 [AtspiAccessible]
         sender = 0x55555585d934 ":1.31"
         path = 0x55555585d940 "/org/a11y/atspi/accessible/5"
         iter_struct = {dummy1 = 0x5555558dd840, dummy2 = 
0x7fff00600000, dummy3 = 108, dummy4 = 0, dummy5 = 1435359304, dummy6 = 
21845, dummy7 = 119, dummy8 = 0, dummy9 = 1435359376, dummy10 = 21845, 
dummy11 = 10, pad1 = 0, pad2 = 0x7ffff5befe20, pad3 = 0x0}
         signature = <optimized out>
         type = <optimized out>
         interface = <optimized out>
         closure = 0x555555964330
         in_process_deferred_messages = 1
#9  0x00007ffff5c0b3bc in process_deferred_message 
(closure=0x555555964330) at atspi-misc.c:753
         type = <optimized out>
         interface = <optimized out>
         closure = 0x555555964330
         in_process_deferred_messages = 1
#10 0x00007ffff5c0b3bc in process_deferred_messages () at atspi-misc.c:774
         closure = 0x555555964330
         in_process_deferred_messages = 1
#11 0x00007ffff5c0b599 in process_deferred_messages () at atspi-misc.c:785
         in_process_deferred_messages = 1
         in_process_deferred_messages = 1
#12 0x00007ffff5c0b599 in process_deferred_messages_callback 
(data=<optimized out>) at atspi-misc.c:786
#13 0x00007ffff56d86aa in g_main_dispatch (context=0x55555576e070) at 
././glib/gmain.c:3203
         dispatch = 0x7ffff56d50d0 <g_idle_dispatch>
         prev_source = 0x0
         was_in_call = 0
         user_data = 0x0
         callback = 0x7ffff5c0b580 <process_deferred_messages_callback>
         cb_funcs = <optimized out>
         cb_data = 0x555555903080
         need_destroy = <optimized out>
         source = 0x555555879730
         current = 0x555555780320
         i = 0
#14 0x00007ffff56d86aa in g_main_context_dispatch 
(context=context@entry=0x55555576e070) at ././glib/gmain.c:3856
#15 0x00007ffff56d8a60 in g_main_context_iterate 
(context=context@entry=0x55555576e070, block=block@entry=1, 
dispatch=dispatch@entry=1, self=<optimized out>) at ././glib/gmain.c:3929
         max_priority = 200
         timeout = 0
         some_ready = 1
         nfds = 4
         allocated_nfds = 4
         fds = <optimized out>
#16 0x00007ffff56d8b0c in g_main_context_iteration 
(context=context@entry=0x55555576e070, may_block=may_block@entry=1) at 
././glib/gmain.c:3990
         retval = <optimized out>
#17 0x00007ffff611572d in g_application_run (application=0x55555576c1a0 
[GtkApplication], argc=1, argv=0x7fffffffe0d8) at 
././gio/gapplication.c:2381
         arguments = 0x555555762420
         status = 0
         context = 0x55555576e070
         acquired_context = <optimized out>
         __func__ = "g_application_run"
#18 0x0000555555554d50 in main (argc=1, argv=0x7fffffffe0d8) at test.c:52
         app = 0x55555576c1a0 [GtkApplication]
         status = 32767

--- backtrace end ----

Any advice is welcome. Is there some online How-do-I for improving 
accessibility? I found only the API reference. It tells me how to do 
something, but first I have to know what to do.

Thank you!
Gabor