Re: libatspi and event processing
- From: Mike Gorse <mgorse alum wpi edu>
- To: Lukasz Stanislawski <l stanislaws samsung com>
- Cc: gnome-accessibility-list gnome org
- Subject: Re: libatspi and event processing
- Date: Wed, 4 Mar 2015 23:14:01 -0500 (EST)
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
gnome-accessibility-list gnome org
https://mail.gnome.org/mailman/listinfo/gnome-accessibility-list
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]