Re: libatspi and event processing
Mike Gorse <[email protected]>
| Newsgroups | gmane.comp.gnome.accessibility.general |
|---|---|
| Message-ID | <[email protected]> |
Not really an answer, but the call to process_deferred_messages() is the interesting bit here. When an AT-SPI event is received, it is queued for later processing via process_deferred_messages, which is executed either in an idle handler or at the end of a method call. Iirc this is done in order to control the order in which events are sent, as it will not recurse. I'm not sure if the process_deferred_messages() calls at the ends of these AT-SPI functions need to be there. Perhaps they should be removed, although I'd be hesitant to remove them for 3.16 this late in the cycle--the code has worked that way for a long time... Feel free to file a bug if you'd like it to be tracked that way. On Tue, 3 Mar 2015, Lukasz Stanislawski wrote: > Hey, thank Tou for quick answer. > > On 02.03.2015 18:39, Alejandro Piñeiro wrote: >> On 02/03/15 18:08, Lukasz Stanislawski wrote: >>> Hello everyone, >>> >>> Currently, I'm developing small C application using libatspi and >>> encountered some problems with event processing. >>> >>> What I have is two event listeners A and B registered with >>> atspi_event_listener_register() on different at-spi events. Inside >>> main loop assume that A listener can invoke callback a() on some atspi >>> event. Inside a() callback there are some calls to >>> atspi_accessible_get_* functions. >>> >>> What I have noticed is that calling functins like. >>> atspi_accessible_get_name() triggers further dbus events processing >>> what result in different listeners to be invoked. >> >> Those get functions need to trigger those dbus events, as the >> information is usually not stored (except if it is already cached) at >> libatspi. It needs to be requested to the client (the application). So >> it is not possible to avoid that dbus triggering, as is the only way to >> get the info you request. >> > Yeah, it is not possible to avoid dbus triggering when method is invoked, > however is it possible not to process mismatching events? (eg. whem > atspi_accessibile_get_name method is invoked only dbus message matching > returning name will be processed) Can rest of events gathered while waiting > for answer be queued and processed when main loop enters idle state? > >>> As the result code of b() callback can be invoked (and sometimes is in >>> my application) during execution of a() callback code.called >> >> About getting the other callback called because a different listener is >> invoked: it is complicated to understand your problem at a so abstract >> level. Could you give a example of what event is triggered when >> atspi_accessible_get_<something> that invokes the second callback? >> > My real life example is a bit different and more complex however I will try > to explain it in details. I have an accessibility application allowing users > to navigate only over specific type of widgets etc, with some various > policies. > > To do this, first of all I have to be able to track what window have > currently input focus. I'm doing it by registering listener on > "window:active" and "object:state-changed:focused". When any of these events > occurs on_window_activate callback is called. > > Secondly. when window receives focus I have to gather all interesting > information from accessibility tree and build my own cache from data that is > not cached by atspi like positions and sizes. It occurred that there are some > performance issues with it, (main loop is blocked too long not allowing other > events to be processed), so I have decided to fetch data partially using > idlers. > > When my own data cache is done I start to process it and through the > processing of data a call to atspi_accessibile_get_role is made. This causes > the issues which I have mentioned earlier. When new "window:active" signal > was send, it will process it and call on_window_activate callback which in my > code - invalidates my cache. > > When atspi_accessible_get_role returns my cache is already invalid. This > resulted in cache errors and I couldn't find out what is happening unless i > have looked into atspi source code. > > This situations mostly happens when application right after gaining focus on > window creates new window and focuses. This is a result backtrace, please > check frame #14, #9 and #0 : > > #0 on_window_activate (data=0x0, window=0xaf560) > at /usr/src/debug/org.tizen.smart-navigator-0.0.1/src/navigator.c:822 > #1 0x0000e4f4 in _on_atspi_window_cb (event=0xd1ff8) > at /usr/src/debug/org.tizen.smart-navigator-0.0.1/src/window_tracker.c:18 > #2 0xb6d9a638 in remove_datum (event=<optimized out>, > user_data=<optimized out>) at atspi-event-listener.c:56 > #3 0xb6d9afd0 in _atspi_send_event (e=0xbefff8d8) > at atspi-event-listener.c:849 > #4 0xb6d9b1c2 in _atspi_dbus_handle_event (bus=<optimized out>, > message=<optimized out>, data=<optimized out>) > at atspi-event-listener.c:979 > #5 0xb6d9d2e0 in process_deferred_message (closure=0xc65a8) > at atspi-misc.c:748 > #6 process_deferred_messages () at atspi-misc.c:787 > #7 process_deferred_messages () at atspi-misc.c:777 > #8 0xb6d9d6f2 in _atspi_dbus_call (obj=<optimized out>, > interface=<optimized out>, method=0xb6da4fc0 "GetRole", error=0x0, > type=0xb6da4fc8 "=>u") at atspi-misc.c:1152 > #9 0xb6d98c3a in atspi_accessible_get_role (obj=0xc2718, > error=<optimized out>) at atspi-accessible.c:473 > #10 0x0000dae0 in _filter_role_cb (container=<optimized out>, > data=<optimized out>, fdata=0x_on_cache_buildedc2718) > at /usr/src/debug/org.tizen.smart-navigator-0.0.1/src/flat_navi.c:153 > --Type <return> to continue, or q <return> to quit-- > #11 0x0000da92 in _accessible_list_split_with_filter (list=0x5a8e8, > cb=0xdac5 <_filter_role_cb>, user_data=0x11e0c <interesting_roles>) > at /usr/src/debug/org.tizen.smart-navigator-0.0.1/src/flat_navi.c:112 > #12 0x0000dc34 in _flat_review_candidates_get (root=<optimized out>) > at /usr/src/debug/org.tizen.smart-navigator-0.0.1/src/flat_navi.c:213 > #13 flat_navi_context_create (root=<optimized out>) > at /usr/src/debug/org.tizen.smart-navigator-0.0.1/src/flat_navi.c:257 > #14 0x0000fa4e in _on_cache_builded (data=<optimized out>) > at /usr/src/debug/org.tizen.smart-navigator-0.0.1/src/navigator.c:802 > #15 0x0000e878 in _do_cache (data=<optimized out>) > at /usr/src/debug/org.tizen.smart-navigator-0.0.1/src/object_cache.c:173 > #16 _do_cache (data=<optimized out>) > at /usr/src/debug/org.tizen.smart-navigator-0.0.1/src/object_cache.c:163 > #17 0xb6e05860 in _ecore_call_task_cb (data=<optimized out>, > func=<optimized out>) at ecore_private.h:272 > #18 _ecore_idler_all_call () at ecore_idler.c:119 > #19 0xb6e067c6 in _ecore_main_loop_spin_core () at ecore_main.c:1746 > #20 0xb6e069d8 in _ecore_main_loop_spin_timers () at ecore_main.c:1780 > #21 _ecore_main_loop_iterate_internal (once_only=0) at ecore_main.c:1903 > #22 0xb6e06dc0 in ecore_main_loop_begin () at ecore_main.c:956 > #23 0xb6fa5ab6 in appcore_efl_main () from /usr/lib/libappcore-efl.so.1 > #24 0x0000bfcc in main (argc=1, argv=0xbefffdc4) > at /usr/src/debug/org.tizen.smart-navigator-0.0.1/src/main.c:71 > > I have managed to solve my issues by simple removing all calls to > atspi_accessible_get_* in my cache processing code. However I was carious if > I'm doing something wrong or just atspi programmer have to be aware that this > can happen. Maybe shouldn't it be better if it worked as I wrote in first at > the begining, What do You think? > >>> >>> I find this very inconvenient because every atspi_accessible_get_* >>> related call in callback a() have to be wrapped with some 'rollback' >>> logic in my application, because events of listener B can occur. >>> >>> So my questions are: >>> >>> 1. What is a preferred way of handling such cases? I want every >>> callback to process sequentially and not to introduce new race >>> conditions in my application. Such APIs makes my code hard to write >>> because "everything can happen everywhere". >> >> As mentioned, if in your callback you call new atspi methods, they would >> need to use dbus to get that info. But it would be good to have a real >> example in order to know why this is problematic. >> >>> 2. Shouldn't it be better to dispatch all deferred events when main >>> loop enters idle state? Mayby there is a reasoning for such design >>> that I'm not familiar of. >> >> You seem to suggest the addition of an asynchronous API. If that is the >> case, it is true that there are some attempts to include an asynchronous >> API in order to solve some issues of the classic libatspi synchronous >> API. But in most cases, libatspi is still an asynchronous API. >> >> BR >> > _______________________________________________ > gnome-accessibility-list mailing list > [email protected] > https://mail.gnome.org/mailman/listinfo/gnome-accessibility-list > _______________________________________________ gnome-accessibility-list mailing list [email protected] https://mail.gnome.org/mailman/listinfo/gnome-accessibility-list