* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-#include "app_tracker.h"
-#include "screen_reader_tts.h"
-#include "window_tracker.h"
-#include "logger.h"
#include <ctype.h>
-#include "navigator.h"
-#include "utils.h"
+
+#include <app_tracker.h>
+#include <logger.h>
+#include <navigator.h>
+#include <screen_reader_tts.h>
+#include <utils.h>
+#include <window_tracker.h>
#ifndef SCREEN_READER_TV
-#include "granularity_read.h"
+#include <granularity_read.h>
#endif
typedef struct {
} EventCallbackData;
// structure defining context of active window
-typedef struct {
+struct _App_Tracker_Data {
AtspiAccessible *root; // accessibility node of active window
EventCallbackData *view_content_changed_ecd; // callback that rebuilds navigation context on significant changes of visible UI
guint timer; // used for defered execution of view_content_changed_ecd callback
-} AppTrackerData;
+ AtspiEventListener *listener;
+
+ AppTrackerEventCB new_obj_highlighted_callback;
+ void *new_obj_highlighted_callback_user_data;
+#ifndef SCREEN_READER_TV
+ Ecore_Timer *read_timer;
+ AtspiAccessible *read_timer_user_data;
+
+ AtspiAccessible *prev_highlighted_obj;
+ AtspiAccessible *scroll_gesture_required_obj;
+#endif
+};
#ifndef SCREEN_READER_TV
static void app_tracker_context_switch(void *data, AtspiAccessible *root);
-static AtspiAccessible *_scroll_gesture_required_obj = NULL;
#endif
#define APP_TRACKER_INVACTIVITY_TIMEOUT 200
#define HIGHLIGHT_UPDATE_READ_TIMEOUT 0.1
-static int _init_count;
-static AppTrackerData *atd = NULL;
-static AtspiEventListener *_listener;
-static AppTrackerEventCB _new_obj_highlighted_callback;
-static void *_new_obj_highlighted_callback_user_data = NULL;
extern bool keyboard_feedback;
-#ifndef SCREEN_READER_TV
-Ecore_Timer *read_timer = NULL;
-AtspiAccessible *prev_highlighted_obj = NULL;
-#endif
-
static gboolean _on_timeout_rebuild_navigation_context(gpointer user_data)
{
DEBUG("START");
return FALSE;
}
- AppTrackerData *atd = (AppTrackerData *)user_data;
+ App_Tracker_Data *atd = (App_Tracker_Data *)user_data;
if (!atd->root || object_has_defunct_state(atd->root)) {
ERROR("Cannot rebuild navigation context. Active window is defunct.");
tts_speak(buf, EINA_TRUE);
}
-static void timer_reschedule(void)
+static void timer_reschedule(App_Tracker_Data *atd)
{
#ifndef SCREEN_READER_TV
- if (read_timer) {
+ if (atd->read_timer) {
DEBUG("Remove read timer before navigation context rebuilding");
- ecore_timer_del(read_timer);
- read_timer = NULL;
+ ecore_timer_del(atd->read_timer);
+ atd->read_timer = NULL;
}
#endif
static Eina_Bool _read_cb(void *data)
{
DEBUG("START");
- AtspiAccessible *current_obj = (AtspiAccessible *)data;
+ App_Tracker_Data *atd = (App_Tracker_Data*)data;
+ AtspiAccessible *current_obj = atd->read_timer_user_data;
generate_what_to_read_and_speak(get_pointer_to_service_data_struct()->navigator_data, current_obj, EINA_TRUE);
- read_timer = NULL;
+ atd->read_timer = NULL;
+ atd->read_timer_user_data = NULL; /* It's on to clean it as we cancel next call. */
sound_n_vibration_feedback_generate(current_obj);
return ECORE_CALLBACK_CANCEL;
}
}
#ifndef SCREEN_READER_TV
-static void _object_needs_scroll_gesture_send(AtspiAccessible *obj)
+static void _object_needs_scroll_gesture_send(App_Tracker_Data *atd, AtspiAccessible *obj)
{
Eldbus_Connection *conn;
Eldbus_Object *dobj;
int highlighted_object_x = -1;
int highlighted_object_y = -1;
- if (!_scroll_gesture_required_obj && !(obj))
+ if (!atd->scroll_gesture_required_obj && !(obj))
return;
eldbus_init();
highlighted_object_y = rect->y + rect->height / 2;
g_free(rect);
}
- _scroll_gesture_required_obj = obj;
+ atd->scroll_gesture_required_obj = obj;
eldbus_proxy_call(proxy, "ObjectNeedsScrollGesture", NULL, NULL, -1, "ii", highlighted_object_x, highlighted_object_y);
}
#endif
-static void _on_atspi_event_cb(const AtspiEvent *event)
+static void _on_atspi_event_cb(AtspiEvent *event, void *user_data)
{
AtspiAccessible *new_highlighted_obj = NULL;
if (!event)
return;
+
if (!event->source) {
ERROR("empty event source");
return;
}
+ if (!user_data) {
+ ERROR("user_data could not be NULL");
+ return;
+ }
+
+ App_Tracker_Data *atd = (App_Tracker_Data*)user_data;
AtspiRole role = atspi_accessible_get_role(event->source, NULL);
if (role == ATSPI_ROLE_DESKTOP_FRAME)
return;
#ifndef SCREEN_READER_TV
if (event->detail1) {//Update highlight object only when grab is called
new_highlighted_obj = event->source;
- if (read_timer) ecore_timer_del(read_timer);
- read_timer = ecore_timer_add(HIGHLIGHT_UPDATE_READ_TIMEOUT, _read_cb, new_highlighted_obj);
- prev_highlighted_obj = new_highlighted_obj;
+ if (atd->read_timer) {
+ ecore_timer_del(atd->read_timer);
+ atd->read_timer_user_data = NULL;
+ }
+
+ atd->read_timer_user_data = new_highlighted_obj;
+ atd->read_timer = ecore_timer_add(HIGHLIGHT_UPDATE_READ_TIMEOUT, _read_cb, atd);
+ atd->prev_highlighted_obj = new_highlighted_obj;
/* send - scroll gesture required info */
if (event->detail2)
- _object_needs_scroll_gesture_send(event->source);
+ _object_needs_scroll_gesture_send(atd, event->source);
} else {
- if (read_timer && prev_highlighted_obj == event->source) {
- gchar *id = atspi_accessible_get_unique_id(prev_highlighted_obj, NULL);
+ if (atd->read_timer && atd->prev_highlighted_obj == event->source) {
+ gchar *id = atspi_accessible_get_unique_id(atd->prev_highlighted_obj, NULL);
DEBUG("Prev highlighted %s lost highlight", id);
g_free(id);
- ecore_timer_del(read_timer);
- read_timer = NULL;
+ ecore_timer_del(atd->read_timer);
+ atd->read_timer = NULL;
+ atd->read_timer_user_data = NULL;
}
granularity_read_text_list_init();
/* unset _scroll_gesture_requrired_obj */
- _object_needs_scroll_gesture_send(NULL);
+ _object_needs_scroll_gesture_send(atd, NULL);
}
#endif
} else if (!g_strcmp0(event->type, "object:active-descendant-changed")) {
} else if (role == ATSPI_ROLE_PAGE_TAB) {
// refresh default label for newly showing page tab
DEBUG("Refreshing TAB");
- timer_reschedule();
+ timer_reschedule(atd);
} else if (object_has_modal_role(role)) {
// push modal to base_root stack
DEBUG("Pushing modal: ROLE: %d", role);
free(text_to_speak);
}
else {
- timer_reschedule();
+ timer_reschedule(atd);
}
}
} else { /* Not Showing */
//TODO: check if source is same with modals->data
// pop modal
DEBUG("Pop modal");
- timer_reschedule();
+ timer_reschedule(atd);
} else if (flat_navi_context_current_get(navigator_get_flat_navi_context(atd->view_content_changed_ecd->user_data)) == event->source) {
DEBUG("Current highlighted object becomes not-showing");
- timer_reschedule();
+ timer_reschedule(atd);
}
}
}
}
}
- if (new_highlighted_obj && _new_obj_highlighted_callback && object_has_highlighted_state(new_highlighted_obj)) {
+ if (new_highlighted_obj && atd->new_obj_highlighted_callback && object_has_highlighted_state(new_highlighted_obj)) {
DEBUG("HIGHLIGHTED OBJECT IS ABOUT TO CHANGE");
- _new_obj_highlighted_callback(new_highlighted_obj, role, _new_obj_highlighted_callback_user_data);
+ atd->new_obj_highlighted_callback(new_highlighted_obj, role, atd->new_obj_highlighted_callback_user_data);
g_object_unref(new_highlighted_obj);
new_highlighted_obj = NULL;
}
DEBUG("END");
}
-static int _app_tracker_init_internal(AppTrackerEventWithDefaultLabelInfoCB view_content_changed_cb, Navigator_Data *nd)
+App_Tracker_Data*
+app_tracker_init(AppTrackerEventWithDefaultLabelInfoCB view_content_changed_cb, Navigator_Data *nd)
{
- DEBUG("START");
+ DEBUG("Alocating active window context");
+ App_Tracker_Data *atd = g_new(App_Tracker_Data, 1);
if (!atd) {
- DEBUG("Alocating active window context");
- atd = g_new(AppTrackerData, 1);
- DEBUG("Context allocated");
- atd->view_content_changed_ecd = g_new(EventCallbackData, 1);
- DEBUG("Callback allocated");
- atd->view_content_changed_ecd->user_data = nd;
- atd->view_content_changed_ecd->func = view_content_changed_cb;
- DEBUG("View content changed callback set func=%p data=%p", view_content_changed_cb, nd);
- atd->root = NULL;
- atd->timer = 0;
- subroot = NULL;
+ ERROR("Memory allocation failed");
+ return NULL;
+ }
+ DEBUG("Context allocated");
+ atd->view_content_changed_ecd = g_new(EventCallbackData, 1);
+ DEBUG("Callback allocated");
+ atd->view_content_changed_ecd->user_data = nd;
+ atd->view_content_changed_ecd->func = view_content_changed_cb;
+ DEBUG("View content changed callback set func=%p data=%p", view_content_changed_cb, nd);
+ atd->root = NULL;
+ atd->timer = 0;
+ subroot = NULL;
#ifndef SCREEN_READER_TV
- window_tracker_init();
- DEBUG("Registering app_tracker_context_switch=%p, for atd=%p", app_tracker_context_switch, atd);
- window_tracker_register(app_tracker_context_switch, atd);
- /* This function does not affect
- window_tracker_active_window_request();
- */
+ atd->read_timer = NULL;
+ atd->read_timer_user_data = NULL;
+ atd->prev_highlighted_obj = NULL;
+ atd->scroll_gesture_required_obj = NULL;
+ window_tracker_init();
+ DEBUG("Registering app_tracker_context_switch=%p, for atd=%p", app_tracker_context_switch, atd);
+ window_tracker_register(app_tracker_context_switch, atd);
+ /* This function does not affect
+ window_tracker_active_window_request();
+ */
#endif
- }
- _new_obj_highlighted_callback = NULL;
- _new_obj_highlighted_callback_user_data = NULL;
- _listener = atspi_event_listener_new_simple(_on_atspi_event_cb, NULL);
-
- atspi_event_listener_register(_listener, "object:state-changed:showing", NULL);
- atspi_event_listener_register(_listener, "object:state-changed:highlighted", NULL);
- atspi_event_listener_register(_listener, "object:state-changed:animated", NULL);
- atspi_event_listener_register(_listener, "object:state-changed:checked", NULL);
- atspi_event_listener_register(_listener, "object:state-changed:selected", NULL);
- atspi_event_listener_register(_listener, "object:bounds-changed", NULL);
- atspi_event_listener_register(_listener, "object:active-descendant-changed", NULL);
- atspi_event_listener_register(_listener, "object:property-change:accessible-name", NULL);
- atspi_event_listener_register(_listener, "object:property-change:accessible-value", NULL);
- atspi_event_listener_register(_listener, "object:text-changed:insert", NULL);
- atspi_event_listener_register(_listener, "object:text-changed:delete", NULL);
- atspi_event_listener_register(_listener, "object:move-outed", NULL);
-
- return 0;
-}
-static void _app_tracker_data_free(AppTrackerData *atd)
-{
- if (atd->timer)
- g_source_remove(atd->timer);
- g_object_unref(atd->root);
- g_free(atd);
+ atd->new_obj_highlighted_callback = NULL;
+ atd->new_obj_highlighted_callback_user_data = NULL;
+ atd->listener = atspi_event_listener_new(_on_atspi_event_cb, atd, NULL);
+
+ atspi_event_listener_register(atd->listener, "object:state-changed:showing", NULL);
+ atspi_event_listener_register(atd->listener, "object:state-changed:highlighted", NULL);
+ atspi_event_listener_register(atd->listener, "object:state-changed:animated", NULL);
+ atspi_event_listener_register(atd->listener, "object:state-changed:checked", NULL);
+ atspi_event_listener_register(atd->listener, "object:state-changed:selected", NULL);
+ atspi_event_listener_register(atd->listener, "object:bounds-changed", NULL);
+ atspi_event_listener_register(atd->listener, "object:active-descendant-changed", NULL);
+ atspi_event_listener_register(atd->listener, "object:property-change:accessible-name", NULL);
+ atspi_event_listener_register(atd->listener, "object:property-change:accessible-value", NULL);
+ atspi_event_listener_register(atd->listener, "object:text-changed:insert", NULL);
+ atspi_event_listener_register(atd->listener, "object:text-changed:delete", NULL);
+ atspi_event_listener_register(atd->listener, "object:move-outed", NULL);
+
+ return atd;
}
-static void _app_tracker_shutdown_internal(void)
+void app_tracker_shutdown(App_Tracker_Data *atd)
{
- atspi_event_listener_deregister(_listener, "object:state-changed:showing", NULL);
- atspi_event_listener_deregister(_listener, "object:state-changed:highlighted", NULL);
- atspi_event_listener_deregister(_listener, "object:state-changed:animated", NULL);
- atspi_event_listener_deregister(_listener, "object:state-changed:checked", NULL);
- atspi_event_listener_deregister(_listener, "object:state-changed:selected", NULL);
- atspi_event_listener_deregister(_listener, "object:bounds-changed", NULL);
- atspi_event_listener_deregister(_listener, "object:active-descendant-changed", NULL);
- atspi_event_listener_deregister(_listener, "object:property-change:accessible-name", NULL);
- atspi_event_listener_deregister(_listener, "object:property-change:accessible-value", NULL);
- atspi_event_listener_deregister(_listener, "object:text-changed:insert", NULL);
- atspi_event_listener_deregister(_listener, "object:text-changed:delete", NULL);
- atspi_event_listener_deregister(_listener, "object:move-outed", NULL);
-
- g_object_unref(_listener);
- _listener = NULL;
- _new_obj_highlighted_callback = NULL;
- if (_new_obj_highlighted_callback_user_data) {
- WARNING("You should deregister _new_obj_highlighted_callback before shutdown!");
+ atspi_event_listener_deregister(atd->listener, "object:state-changed:showing", NULL);
+ atspi_event_listener_deregister(atd->listener, "object:state-changed:highlighted", NULL);
+ atspi_event_listener_deregister(atd->listener, "object:state-changed:animated", NULL);
+ atspi_event_listener_deregister(atd->listener, "object:state-changed:checked", NULL);
+ atspi_event_listener_deregister(atd->listener, "object:state-changed:selected", NULL);
+ atspi_event_listener_deregister(atd->listener, "object:bounds-changed", NULL);
+ atspi_event_listener_deregister(atd->listener, "object:active-descendant-changed", NULL);
+ atspi_event_listener_deregister(atd->listener, "object:property-change:accessible-name", NULL);
+ atspi_event_listener_deregister(atd->listener, "object:property-change:accessible-value", NULL);
+ atspi_event_listener_deregister(atd->listener, "object:text-changed:insert", NULL);
+ atspi_event_listener_deregister(atd->listener, "object:text-changed:delete", NULL);
+ atspi_event_listener_deregister(atd->listener, "object:move-outed", NULL);
+
+ g_object_unref(atd->listener);
+ atd->listener = NULL;
+
+ atd->new_obj_highlighted_callback = NULL;
+ if (atd->new_obj_highlighted_callback_user_data) {
+ WARNING("You should deregister new_obj_highlighted_callback before shutdown!");
}
- _new_obj_highlighted_callback_user_data = NULL;
+ atd->new_obj_highlighted_callback_user_data = NULL;
#ifndef SCREEN_READER_TV
- if (read_timer) ecore_timer_del(read_timer);
- read_timer = NULL;
+ if (atd->read_timer)
+ ecore_timer_del(atd->read_timer);
+ atd->read_timer = NULL;
#endif
- if (atd) _app_tracker_data_free(atd);
- atd = NULL;
-}
-
-int app_tracker_init(AppTrackerEventWithDefaultLabelInfoCB view_content_changed_cb, Navigator_Data *nd)
-{
- DEBUG("START");
- if (!(_init_count++))
- if (_app_tracker_init_internal(view_content_changed_cb, nd)) {
- _init_count--;
- return -1;
- }
- return _init_count;
-}
+ if (atd->timer)
+ g_source_remove(atd->timer);
-void app_tracker_shutdown(void)
-{
- if (_init_count == 1)
- _app_tracker_shutdown_internal();
- if (--_init_count < 0)
- _init_count = 0;
+ g_object_unref(atd->root);
+ g_free(atd);
}
#ifndef SCREEN_READER_TV
static void app_tracker_context_switch(void *data, AtspiAccessible *root)
{
- AppTrackerData *atd = (AppTrackerData *)data;
- if (!_init_count || !atd) {
+ App_Tracker_Data *atd = (App_Tracker_Data *)data;
+ if (!atd) {
ERROR("app_tracker module used without initialization");
return;
}
}
/* unset _scroll_gesture_requrired_obj */
- _object_needs_scroll_gesture_send(NULL);
+ _object_needs_scroll_gesture_send(atd, NULL);
atd->root = root;
- timer_reschedule();
+ timer_reschedule(atd);
}
#endif
-void app_tracker_new_obj_highlighted_callback_register(AppTrackerEventCB cb, void *user_data)
+void app_tracker_new_obj_highlighted_callback_register(App_Tracker_Data *atd, AppTrackerEventCB cb, void *user_data)
{
- if (_new_obj_highlighted_callback) {
+ if (atd->new_obj_highlighted_callback) {
ERROR("Only one callback is allowed!");
return;
}
- _new_obj_highlighted_callback = cb;
- _new_obj_highlighted_callback_user_data = user_data;
+ atd->new_obj_highlighted_callback = cb;
+ atd->new_obj_highlighted_callback_user_data = user_data;
}
-void* app_tracker_new_obj_highlighted_callback_unregister()
+void* app_tracker_new_obj_highlighted_callback_unregister(App_Tracker_Data *atd)
{
- _new_obj_highlighted_callback = NULL;
- void *ret = _new_obj_highlighted_callback_user_data;
- _new_obj_highlighted_callback_user_data = NULL;
+ atd->new_obj_highlighted_callback = NULL;
+ void *ret = atd->new_obj_highlighted_callback_user_data;
+ atd->new_obj_highlighted_callback_user_data = NULL;
return ret;
}
-AppTrackerContextValidility app_tracker_context_valid_check(void)
+AppTrackerContextValidility app_tracker_context_valid_check(App_Tracker_Data *atd)
{
if (atd->timer) {
DEBUG("timer is active");
return APP_TRACKER_CONTEXT_NOT_VALID;
}
-void app_tracker_scroll_gesture_required_object_info_send(void)
+void app_tracker_scroll_gesture_required_object_info_send(App_Tracker_Data *atd)
{
#ifndef SCREEN_READER_TV
- /* If _scroll_gesture_required_obj is NULL, then send -1, -1 */
- _object_needs_scroll_gesture_send(_scroll_gesture_required_obj);
+ /* If scroll_gesture_required_obj is NULL, then send -1, -1 */
+ _object_needs_scroll_gesture_send(atd, atd->scroll_gesture_required_obj);
#endif
}