From: Lukasz Wlazly Date: Fri, 9 Sep 2016 07:52:52 +0000 (+0200) Subject: [screen reader] Code refactoring: navigator X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fheads%2Ftizen-refactored-v2;p=platform%2Fcore%2Faccessibility%2Fscreen-reader.git [screen reader] Code refactoring: navigator Change-Id: I309397981b0ab1054228cab78e423d48b2546ced --- diff --git a/include/navigator.h b/include/navigator.h index f9b69250..9ae6a1a6 100644 --- a/include/navigator.h +++ b/include/navigator.h @@ -1,3 +1,6 @@ +#ifndef NAVIGATOR_H_ +#define NAVIGATOR_H_ + #include #include "screen_reader.h" @@ -6,5 +9,22 @@ extern bool read_description; extern bool haptic; -void navigator_init(void); -void navigator_shutdown(void); + +/** + * @brief Creates environment for navigation + * @description Initializes D-Bus Gesture Adapter, App Tracker, Window Tracker, + * registers callback functions for gesture detection and highlight changing + * + * @note Initializes notification system if SCREEN_READER_TV is undefined + * + * @see app_tracker_init(), window_tracker_init(), smart_notification_init(), system_notifications_init() + */ +Navigator_Data *navigator_init(Service_Data *sd); + +/** + * @brief Closes all subservices opened in initialization + * + */ +void navigator_shutdown(Service_Data *sd); + +#endif //NAVIGATOR_H_ diff --git a/include/screen_reader.h b/include/screen_reader.h index da6ecac5..106bf098 100644 --- a/include/screen_reader.h +++ b/include/screen_reader.h @@ -26,47 +26,50 @@ typedef struct typedef enum { - read_as_xml, - read_as_plain, - dont_read + read_as_xml, + read_as_plain, + dont_read } Wrong_Validation_Reacction; +typedef struct _Navigator_Data Navigator_Data; + typedef struct _Service_Data { - //Set by vconf - bool run_service; - char display_language[LANGUAGE_NAME_SIZE]; - char *tracking_signal_name; - - //Set by tts - tts_h tts; - Eina_List *available_languages; - - char *text_to_say_info; - char *current_value; - char *current_char; - - //Actions to do when tts state is 'ready' - int _dbus_txt_readed; - bool say_text; - bool update_language_list; - - //Set by spi - AtspiEventListener *state_changed_listener; - AtspiEventListener *value_changed_listener; - AtspiEventListener *caret_moved_listener; - AtspiEventListener *spi_listener; - - AtspiAccessible *currently_focused; - AtspiAccessible *mouse_down_widget; - AtspiAccessible *clicked_widget; - - //Set by dbus - Eldbus_Proxy *proxy; - char **last_tokens; - char *available_requests; - char **available_apps; - + Navigator_Data *navigator_data; + + //Set by vconf + bool run_service; + char display_language[LANGUAGE_NAME_SIZE]; + char *tracking_signal_name; + + //Set by tts + tts_h tts; + Eina_List *available_languages; + + char *text_to_say_info; + char *current_value; + char *current_char; + + //Actions to do when tts state is 'ready' + int _dbus_txt_readed; + bool say_text; + bool update_language_list; + + //Set by spi + AtspiEventListener *state_changed_listener; + AtspiEventListener *value_changed_listener; + AtspiEventListener *caret_moved_listener; + AtspiEventListener *spi_listener; + + AtspiAccessible *currently_focused; + AtspiAccessible *mouse_down_widget; + AtspiAccessible *clicked_widget; + + //Set by dbus + Eldbus_Proxy *proxy; + char **last_tokens; + char *available_requests; + char **available_apps; } Service_Data; Service_Data *get_pointer_to_service_data_struct(); diff --git a/src/main.c b/src/main.c index e856ce1a..c0bfd040 100644 --- a/src/main.c +++ b/src/main.c @@ -216,6 +216,8 @@ void set_signal_handler() static int app_create(void *data) { + Service_Data *sd = get_pointer_to_service_data_struct(); + elm_init(0, NULL); atspi_init(); screen_reader_create_service(data); @@ -226,7 +228,12 @@ static int app_create(void *data) } #ifndef SCREEN_READER_TV //screen_reader_gestures_init(); - navigator_init(); + sd->navigator_data = navigator_init(sd); + if (sd->navigator_data == NULL) { + ERROR("Navigator not initialized"); + return -1; + } + keyboard_tracker_init(); #endif screen_reader_switch_enabled_set(EINA_TRUE); @@ -236,10 +243,12 @@ static int app_create(void *data) static int app_terminate(void *data) { + Service_Data *sd = get_pointer_to_service_data_struct(); + DEBUG("screen reader terminating"); #ifndef SCREEN_READER_TV DEBUG("terminate navigator"); - navigator_shutdown(); + navigator_shutdown(sd); DEBUG("terminate gestures"); //screen_reader_gestures_shutdown(); #endif diff --git a/src/navigator.c b/src/navigator.c index 14f433b3..b7a86976 100644 --- a/src/navigator.c +++ b/src/navigator.c @@ -75,8 +75,9 @@ static void on_window_activate(void *data, AtspiAccessible * window); static void _highlight_on_slider(Eina_Bool is_slider); typedef struct { - int x, y; -} last_focus_t; + int x; + int y; +} point_t; /* The Highlight_Type will be used for access object working for embedded toolkit such as Dali does not support at-spi interface. This kind of work @@ -89,27 +90,26 @@ typedef enum { HIGHLIGHT_PREV } Highlight_Type; -static last_focus_t gesture_start_p = { -1, -1 }; -static last_focus_t last_focus = { -1, -1 }; -static last_focus_t last_pos = { -1, -1 }; +struct _Navigator_Data { + point_t gesture_start_p; + point_t last_focus; + point_t last_pos; + AtspiAccessible *current_obj; + AtspiComponent *current_comp; + AtspiAccessible *top_window; + bool prepared; + int counter; + int last_hover_event_time; + AtspiAccessible *focused_object; + bool auto_review_on; +}; -static AtspiAccessible *current_obj; -static AtspiComponent *current_comp = NULL; -static AtspiAccessible *top_window; static FlatNaviContext *context; -static bool prepared = false; -static int counter = 0; -int _last_hover_event_time = -1; + extern bool read_description; extern bool haptic; extern bool sound_feedback; -static struct { - AtspiAccessible *focused_object; - bool auto_review_on; -} s_auto_review = { -.focused_object = NULL,.auto_review_on = false}; - char *state_to_char(AtspiStateType state) { switch (state) { @@ -1083,28 +1083,31 @@ static Eina_Bool _highlight_access_object(AtspiAccessible *obj, Highlight_Type h return _do_action(obj, expected_action); } -static void _current_highlight_object_set(AtspiAccessible * obj, Highlight_Type h_type) +static void _current_highlight_object_set(Navigator_Data *nd, AtspiAccessible * obj, Highlight_Type h_type) { DEBUG("START"); + GError *err = NULL; gchar *role_name = NULL; AtspiRole role = -1; if (!obj) { DEBUG("Clearing highlight object"); - current_obj = NULL; - if (current_comp) { - atspi_component_clear_highlight(current_comp, &err); - g_object_unref(current_comp); - current_comp = NULL; + nd->current_obj = NULL; + if (nd->current_comp) { + atspi_component_clear_highlight(nd->current_comp, &err); + g_object_unref(nd->current_comp); + nd->current_comp = NULL; } return; } - if (current_obj == obj) { + + if (nd->current_obj == obj) { DEBUG("Object already highlighted"); DEBUG("Object name:%s", atspi_accessible_get_name(obj, NULL)); return; } + if (obj && ATSPI_IS_COMPONENT(obj)) { DEBUG("OBJ WITH COMPONENT"); AtspiComponent *comp = atspi_accessible_get_component_iface(obj); @@ -1116,8 +1119,8 @@ static void _current_highlight_object_set(AtspiAccessible * obj, Highlight_Type g_free(role_name); return; } - if (current_comp) { - atspi_component_clear_highlight(current_comp, &err); + if (nd->current_comp) { + atspi_component_clear_highlight(nd->current_comp, &err); } if (sound_feedback) { @@ -1145,7 +1148,7 @@ static void _current_highlight_object_set(AtspiAccessible * obj, Highlight_Type } atspi_component_grab_highlight(comp, &err); } - current_comp = comp; + nd->current_comp = comp; GERROR_CHECK(err) Eina_Bool is_paused = tts_pause_get(); @@ -1153,8 +1156,8 @@ static void _current_highlight_object_set(AtspiAccessible * obj, Highlight_Type tts_stop_set(); tts_pause_set(EINA_FALSE); } - g_clear_object(¤t_obj); - current_obj = obj; + g_clear_object(&nd->current_obj); + nd->current_obj = obj; char *text_to_speak = NULL; text_to_speak = generate_what_to_read(obj); DEBUG("SPEAK:%s", text_to_speak); @@ -1204,26 +1207,27 @@ void test_debug(AtspiAccessible * current_widget) g_object_unref(parent); } -static void _focus_widget(Gesture_Info * info) +static void _focus_widget(Navigator_Data *nd, Gesture_Info *info) { DEBUG("START"); - if ((last_focus.x == info->x_beg) && (last_focus.y == info->y_beg)) + if ((nd->last_focus.x == info->x_beg) && (nd->last_focus.y == info->y_beg)) return; AtspiAccessible *obj = NULL; if (flat_navi_context_current_at_x_y_set(context, info->x_beg, info->y_beg, &obj)) { - last_focus.x = info->x_beg; - last_focus.y = info->y_beg; - _current_highlight_object_set(obj, HIGHLIGHT_POINT); + nd->last_focus.x = info->x_beg; + nd->last_focus.y = info->y_beg; + _current_highlight_object_set(nd, obj, HIGHLIGHT_POINT); } DEBUG("END"); } -static void _focus_next(void) +static void _focus_next(Navigator_Data *nd) { DEBUG("START"); + AtspiAccessible *obj; if (!context) { ERROR("No navigation context created"); @@ -1232,15 +1236,16 @@ static void _focus_next(void) obj = flat_navi_context_next(context); if (obj) - _current_highlight_object_set(obj, HIGHLIGHT_FIRST); + _current_highlight_object_set(nd, obj, HIGHLIGHT_FIRST); else DEBUG("Next widget not found. Abort"); DEBUG("END"); } -static void _focus_next_visible(void) +static void _focus_next_visible(Navigator_Data *nd) { DEBUG("START"); + AtspiAccessible *obj; AtspiStateSet *ss = NULL; Eina_Bool visible = EINA_FALSE; @@ -1261,13 +1266,13 @@ static void _focus_next_visible(void) while (obj && !visible); if (obj) - _current_highlight_object_set(obj, HIGHLIGHT_FIRST); + _current_highlight_object_set(nd, obj, HIGHLIGHT_FIRST); else DEBUG("Next widget not found. Abort"); DEBUG("END"); } -static void _focus_prev_visible(void) +static void _focus_prev_visible(Navigator_Data *nd) { AtspiAccessible *obj; AtspiStateSet *ss = NULL; @@ -1288,12 +1293,12 @@ static void _focus_prev_visible(void) while (obj && !visible); if (obj) - _current_highlight_object_set(obj, HIGHLIGHT_LAST); + _current_highlight_object_set(nd, obj, HIGHLIGHT_LAST); else DEBUG("Previous widget not found. Abort"); } -static void _focus_prev(void) +static void _focus_prev(Navigator_Data *nd) { AtspiAccessible *obj; if (!context) { @@ -1303,26 +1308,26 @@ static void _focus_prev(void) obj = flat_navi_context_prev(context); if (obj) - _current_highlight_object_set(obj, HIGHLIGHT_LAST); + _current_highlight_object_set(nd, obj, HIGHLIGHT_LAST); else DEBUG("Previous widget not found. Abort"); } -static void _caret_move_beg(void) +static void _caret_move_beg(Navigator_Data *nd) { AtspiAccessible *current_widget = NULL; AtspiText *text_interface; gboolean ret; GError *err = NULL; - if (!current_obj) + if (!nd->current_obj) return; - AtspiAccessible *relation = flat_navi_get_object_in_relation(current_obj, ATSPI_RELATION_CONTROLLER_FOR); + AtspiAccessible *relation = flat_navi_get_object_in_relation(nd->current_obj, ATSPI_RELATION_CONTROLLER_FOR); if(relation) current_widget = relation; else - current_widget = current_obj; + current_widget = nd->current_obj; text_interface = atspi_accessible_get_text_iface(current_widget); @@ -1336,8 +1341,8 @@ static void _caret_move_beg(void) DEBUG("Caret position increment done"); gchar *text = atspi_text_get_text(text_interface, 0, 1, NULL); DEBUG("SPEAK:%s", text); - tts_speak_customized(text, EINA_TRUE, EINA_TRUE, current_obj); - tts_speak_customized(_("IDS_TEXT_BEGIN"), EINA_FALSE, EINA_TRUE, current_obj); + tts_speak_customized(text, EINA_TRUE, EINA_TRUE, nd->current_obj); + tts_speak_customized(_("IDS_TEXT_BEGIN"), EINA_FALSE, EINA_TRUE, nd->current_obj); g_free(text); } else { ERROR("Caret position increment error"); @@ -1347,21 +1352,21 @@ static void _caret_move_beg(void) ERROR("No text interface supported!"); } -static void _caret_move_end(void) +static void _caret_move_end(Navigator_Data *nd) { AtspiAccessible *current_widget = NULL; AtspiText *text_interface; gboolean ret; GError *err = NULL; - if (!current_obj) + if (nd->current_obj == NULL) return; - AtspiAccessible *relation = flat_navi_get_object_in_relation(current_obj, ATSPI_RELATION_CONTROLLER_FOR); + AtspiAccessible *relation = flat_navi_get_object_in_relation(nd->current_obj, ATSPI_RELATION_CONTROLLER_FOR); if(relation) current_widget = relation; else - current_widget = current_obj; + current_widget = nd->current_obj; text_interface = atspi_accessible_get_text_iface(current_widget); @@ -1374,14 +1379,14 @@ static void _caret_move_end(void) if (ret) { DEBUG("Caret position increment done"); DEBUG("SPEAK:%s", _("IDS_TEXT_END")); - tts_speak_customized(_("IDS_TEXT_END"), EINA_TRUE, EINA_TRUE, current_obj); + tts_speak_customized(_("IDS_TEXT_END"), EINA_TRUE, EINA_TRUE, nd->current_obj); } else ERROR("Caret position to end error"); g_object_unref(text_interface); } } -static void _caret_move_forward(void) +static void _caret_move_forward(Navigator_Data *nd) { AtspiAccessible *current_widget = NULL; AtspiText *text_interface; @@ -1390,14 +1395,14 @@ static void _caret_move_forward(void) int offset_pos; gchar *text; GError *err = NULL; - if (!current_obj) + if (nd->current_obj == NULL) return; - AtspiAccessible *relation = flat_navi_get_object_in_relation(current_obj, ATSPI_RELATION_CONTROLLER_FOR); + AtspiAccessible *relation = flat_navi_get_object_in_relation(nd->current_obj, ATSPI_RELATION_CONTROLLER_FOR); if(relation) current_widget = relation; else - current_widget = current_obj; + current_widget = nd->current_obj; text_interface = atspi_accessible_get_text_iface(current_widget); @@ -1417,10 +1422,10 @@ static void _caret_move_forward(void) DEBUG("Current caret offset:%d", current_offset); if (offset_pos == atspi_text_get_character_count(text_interface, NULL)) { DEBUG("SPEAK:%s", _("IDS_TEXT_END")); - tts_speak_customized(_("IDS_TEXT_END"), EINA_FALSE, EINA_TRUE, current_obj); + tts_speak_customized(_("IDS_TEXT_END"), EINA_FALSE, EINA_TRUE, nd->current_obj); } else { DEBUG("SPEAK:%s", text); - tts_speak_customized(text, EINA_TRUE, EINA_TRUE, current_obj); + tts_speak_customized(text, EINA_TRUE, EINA_TRUE, nd->current_obj); } g_free(text); } else { @@ -1433,7 +1438,7 @@ static void _caret_move_forward(void) } -static void _caret_move_backward(void) +static void _caret_move_backward(Navigator_Data *nd) { AtspiAccessible *current_widget = NULL; AtspiText *text_interface; @@ -1443,14 +1448,14 @@ static void _caret_move_backward(void) GError *err = NULL; gboolean ret; - if (!current_obj) + if (nd->current_obj == NULL) return; - AtspiAccessible *relation = flat_navi_get_object_in_relation(current_obj, ATSPI_RELATION_CONTROLLER_FOR); + AtspiAccessible *relation = flat_navi_get_object_in_relation(nd->current_obj, ATSPI_RELATION_CONTROLLER_FOR); if(relation) current_widget = relation; else - current_widget = current_obj; + current_widget = nd->current_obj; GERROR_CHECK(err) @@ -1470,11 +1475,11 @@ static void _caret_move_backward(void) DEBUG("Caret position decrement done"); DEBUG("Current caret position:%d", offset_pos); DEBUG("SPEAK:%s", text); - tts_speak_customized(text, EINA_TRUE, EINA_TRUE, current_obj); + tts_speak_customized(text, EINA_TRUE, EINA_TRUE, nd->current_obj); g_free(text); if (offset_pos == 0) { DEBUG("SPEAK:%s", _("IDS_TEXT_BEGIN")); - tts_speak_customized(_("IDS_TEXT_BEGIN"), EINA_FALSE, EINA_TRUE, current_obj); + tts_speak_customized(_("IDS_TEXT_BEGIN"), EINA_FALSE, EINA_TRUE, nd->current_obj); } } else { ERROR("Caret position decrement error"); @@ -1485,19 +1490,19 @@ static void _caret_move_backward(void) return; } -static void _value_inc(void) +static void _value_inc(Navigator_Data *nd) { AtspiAccessible *current_widget = NULL; GError *err = NULL; - if (!current_obj) + if (nd->current_obj == NULL) return; - AtspiAccessible *relation = flat_navi_get_object_in_relation(current_obj, ATSPI_RELATION_CONTROLLER_FOR); + AtspiAccessible *relation = flat_navi_get_object_in_relation(nd->current_obj, ATSPI_RELATION_CONTROLLER_FOR); if(relation) current_widget = relation; else - current_widget = current_obj; + current_widget = nd->current_obj; AtspiValue *value_interface = atspi_accessible_get_value_iface(current_widget); @@ -1519,19 +1524,19 @@ static void _value_inc(void) ERROR("No value interface supported!\n"); } -static void _value_dec(void) +static void _value_dec(Navigator_Data *nd) { AtspiAccessible *current_widget = NULL; GError *err = NULL; - if (!current_obj) + if (nd->current_obj == NULL) return; - AtspiAccessible *relation = flat_navi_get_object_in_relation(current_obj, ATSPI_RELATION_CONTROLLER_FOR); + AtspiAccessible *relation = flat_navi_get_object_in_relation(nd->current_obj, ATSPI_RELATION_CONTROLLER_FOR); if(relation) current_widget = relation; else - current_widget = current_obj; + current_widget = nd->current_obj; AtspiValue *value_interface = atspi_accessible_get_value_iface(current_widget); @@ -1553,7 +1558,7 @@ static void _value_dec(void) ERROR("No value interface supported!\n"); } -static void _activate_widget(void) +static void _activate_widget(Navigator_Data *nd) { //activate the widget //only if activate mean click @@ -1575,19 +1580,19 @@ static void _activate_widget(void) Eina_Bool activate_found = EINA_FALSE; AtspiRole role = ATSPI_ROLE_INVALID; - if (!current_obj) + if (nd->current_obj == NULL) return; - if (!_widget_has_state(current_obj, ATSPI_STATE_ENABLED)) { + if (!_widget_has_state(nd->current_obj, ATSPI_STATE_ENABLED)) { DEBUG("Widget is disabled so cannot be activated"); return; } - AtspiAccessible *relation = flat_navi_get_object_in_relation(current_obj, ATSPI_RELATION_CONTROLLER_FOR); + AtspiAccessible *relation = flat_navi_get_object_in_relation(nd->current_obj, ATSPI_RELATION_CONTROLLER_FOR); if(relation) current_widget = relation; else - current_widget = current_obj; + current_widget = nd->current_obj; role = atspi_accessible_get_role(current_widget, NULL); if (role == ATSPI_ROLE_SLIDER) { @@ -1720,13 +1725,13 @@ _find_scrollable_ancestor_at_xy(int x, int y) AtspiRect *rect; GError *err = NULL; - if (!top_window || !ATSPI_IS_COMPONENT(top_window)) + if (!nd->top_window || !ATSPI_IS_COMPONENT(nd->top_window)) { DEBUG("No active window detected or no AtspiComponent interface available"); return NULL; } - rect = atspi_component_get_extents(ATSPI_COMPONENT(top_window), ATSPI_COORD_TYPE_SCREEN, &err); + rect = atspi_component_get_extents(ATSPI_COMPONENT(nd->top_window), ATSPI_COORD_TYPE_SCREEN, &err); GERROR_CHECK(err) if (!rect) { @@ -1743,7 +1748,7 @@ _find_scrollable_ancestor_at_xy(int x, int y) return NULL; } - ret = atspi_component_get_accessible_at_point(ATSPI_COMPONENT(top_window), x, y, ATSPI_COORD_TYPE_SCREEN, &err); + ret = atspi_component_get_accessible_at_point(ATSPI_COMPONENT(nd->top_window), x, y, ATSPI_COORD_TYPE_SCREEN, &err); GERROR_CHECK(err) if (!ret) { @@ -1753,7 +1758,7 @@ _find_scrollable_ancestor_at_xy(int x, int y) gchar *name; gchar *role; // find accessible object with Scrollable interface - while (ret && (ret != top_window)) + while (ret && (ret != nd->top_window)) { name = atspi_accessible_get_name(ret, &err); GERROR_CHECK(err) @@ -1844,14 +1849,25 @@ static void _widget_scroll_end(Gesture_Info *gi) } */ -static void _widget_scroll(Gesture_Info * gi) +static void _widget_scroll(Navigator_Data *nd, Gesture_Info *gi) { DEBUG("Recognized gesture state: %d", gi->state); int x_diff, y_diff; + + if (nd == NULL) { + ERROR("NULL context"); + return; + } + + if (gi == NULL) { + ERROR("NULL gesture"); + return; + } + if (gi->state == 0) { - DEBUG("save coordinates %d %d", gesture_start_p.x, gesture_start_p.y); - gesture_start_p.x = gi->x_beg; - gesture_start_p.y = gi->y_beg; + DEBUG("save coordinates %d %d", nd->gesture_start_p.x, nd->gesture_start_p.y); + nd->gesture_start_p.x = gi->x_beg; + nd->gesture_start_p.y = gi->y_beg; } if (gi->state != 2) { @@ -1861,48 +1877,48 @@ static void _widget_scroll(Gesture_Info * gi) AtspiAccessible *obj = NULL; obj = flat_navi_context_current_get(context); - if (!obj) { + if (obj == NULL) { ERROR("No context"); return; } AtspiStateSet *ss = atspi_accessible_get_state_set(obj); - if (!ss) { + if (ss == NULL) { ERROR("no stetes"); return; } if (!atspi_state_set_contains(ss, ATSPI_STATE_SHOWING)) { DEBUG("current context do not have visible state, swith to next/prev %d %d", gi->x_end,gi->y_end); - x_diff = (gi->x_end - gesture_start_p.x); - y_diff = (gi->y_end - gesture_start_p.y); + x_diff = (gi->x_end - nd->gesture_start_p.x); + y_diff = (gi->y_end - nd->gesture_start_p.y); DEBUG("%d %d", y_diff, x_diff); if (abs(y_diff) >= abs(x_diff)) { if (y_diff > 0) { DEBUG("PREVIOUS"); - _focus_prev_visible(); + _focus_prev_visible(nd); } else { DEBUG("NEXT"); - _focus_next_visible(); + _focus_next_visible(nd); } } else { if (x_diff > 0) { DEBUG("PREVIOUS"); - _focus_prev_visible(); + _focus_prev_visible(nd); } else { DEBUG("NEXT"); - _focus_next_visible(); + _focus_next_visible(nd); } } } else { DEBUG("Read Highlighted object"); char *text_to_speak = NULL; - text_to_speak = generate_what_to_read(current_obj); - tts_speak_customized(text_to_speak, EINA_TRUE, EINA_TRUE, current_obj); + text_to_speak = generate_what_to_read(nd->current_obj); + tts_speak_customized(text_to_speak, EINA_TRUE, EINA_TRUE, nd->current_obj); } DEBUG("end"); @@ -1942,27 +1958,32 @@ static void _set_pause(void) DEBUG("END"); } -void auto_review_highlight_set(void) +void auto_review_highlight_set(Navigator_Data *nd) { + if (nd == NULL) { + ERROR("NULL context"); + return; + } + AtspiAccessible *obj = flat_navi_context_next(context); DEBUG("START"); if (!obj) { DEBUG("obj == NULL"); - s_auto_review.auto_review_on = false; + nd->auto_review_on = false; return; } else if (obj == flat_navi_context_last_get(context)) { DEBUG("obj == flat_navi_context_last_get()"); - s_auto_review.auto_review_on = false; + nd->auto_review_on = false; } - _current_highlight_object_set(obj, HIGHLIGHT_FIRST); + _current_highlight_object_set(nd, obj, HIGHLIGHT_FIRST); DEBUG("END"); } -void auto_review_highlight_top(void) +void auto_review_highlight_top(Navigator_Data *nd) { DEBUG("START"); char *text_to_speak = NULL; @@ -1970,7 +1991,7 @@ void auto_review_highlight_top(void) AtspiAccessible *first = flat_navi_context_first(context); if (first != obj) { - _current_highlight_object_set(first, HIGHLIGHT_FIRST); + _current_highlight_object_set(nd, first, HIGHLIGHT_FIRST); } else { text_to_speak = generate_what_to_read(obj); DEBUG("Text to speak: %s", text_to_speak); @@ -1981,47 +2002,55 @@ void auto_review_highlight_top(void) DEBUG("END"); } -static void _on_auto_review_stop(void) +static void _on_auto_review_stop(Navigator_Data *nd) { DEBUG("START"); - s_auto_review.auto_review_on = false; + nd->auto_review_on = false; DEBUG("END"); } -static void _on_utterance(void) +static void _on_utterance() { DEBUG("START"); - DEBUG("s_auto_review.auto_review_on == %d", s_auto_review.auto_review_on); - if (s_auto_review.auto_review_on) { - auto_review_highlight_set(); + Service_Data *sd = get_pointer_to_service_data_struct(); + + if (sd == NULL) { + ERROR("NULL context"); + return; + } + + DEBUG("sd->navigator_data->auto_review_on == %d", sd->navigator_data->auto_review_on); + + if (sd->navigator_data->auto_review_on) { + auto_review_highlight_set(sd->navigator_data); } DEBUG("END"); } -static void _review_from_current(void) +static void _review_from_current(Navigator_Data *nd) { DEBUG("START"); - s_auto_review.focused_object = flat_navi_context_current_get(context); - s_auto_review.auto_review_on = true; - auto_review_highlight_set(); + nd->focused_object = flat_navi_context_current_get(context); + nd->auto_review_on = true; + auto_review_highlight_set(nd); DEBUG("END"); } -static void _review_from_top() +static void _review_from_top(Navigator_Data *nd) { DEBUG("START"); - s_auto_review.focused_object = flat_navi_context_current_get(context); - s_auto_review.auto_review_on = true; - auto_review_highlight_top(); + nd->focused_object = flat_navi_context_current_get(context); + nd->auto_review_on = true; + auto_review_highlight_top(nd); DEBUG("END"); } -static void _direct_scroll_back(void) +static void _direct_scroll_back(Navigator_Data *nd) { DEBUG("ONE_FINGER_FLICK_LEFT_RETURN"); if (!context) { @@ -2074,13 +2103,13 @@ static void _direct_scroll_back(void) if (flat_navi_context_current_set(context, obj)) { DEBUG("current obj set"); } - _current_highlight_object_set(obj, HIGHLIGHT_FIRST); + _current_highlight_object_set(nd, obj, HIGHLIGHT_FIRST); } g_object_unref(parent); g_object_unref(current); } -static void _direct_scroll_forward(void) +static void _direct_scroll_forward(Navigator_Data *nd) { DEBUG("ONE_FINGER_FLICK_RIGHT_RETURN"); @@ -2134,13 +2163,13 @@ static void _direct_scroll_forward(void) if (flat_navi_context_current_set(context, obj)) { DEBUG("current obj set"); } - _current_highlight_object_set(obj, HIGHLIGHT_LAST); + _current_highlight_object_set(nd, obj, HIGHLIGHT_LAST); } g_object_unref(parent); g_object_unref(current); } -static void _direct_scroll_to_first(void) +static void _direct_scroll_to_first(Navigator_Data *nd) { DEBUG("ONE_FINGER_FLICK_UP_RETURN"); if (!context) { @@ -2149,13 +2178,13 @@ static void _direct_scroll_to_first(void) } AtspiAccessible *obj = flat_navi_context_first(context); if (obj) - _current_highlight_object_set(obj, HIGHLIGHT_FIRST); + _current_highlight_object_set(nd, obj, HIGHLIGHT_FIRST); else DEBUG("First widget not found. Abort"); DEBUG("END"); } -static void _direct_scroll_to_last(void) +static void _direct_scroll_to_last(Navigator_Data *nd) { DEBUG("ONE_FINGER_FLICK_DOWN_RETURN"); if (!context) { @@ -2164,25 +2193,25 @@ static void _direct_scroll_to_last(void) } AtspiAccessible *obj = flat_navi_context_last(context); if (obj) - _current_highlight_object_set(obj, HIGHLIGHT_LAST); + _current_highlight_object_set(nd, obj, HIGHLIGHT_LAST); else DEBUG("Last widget not found. Abort"); DEBUG("END"); } -static Eina_Bool _has_value(void) +static Eina_Bool _has_value(Navigator_Data *nd) { DEBUG("START"); AtspiAccessible *obj = NULL; - if (!current_obj) + if (nd->current_obj == NULL) return EINA_FALSE; - AtspiAccessible *relation = flat_navi_get_object_in_relation(current_obj, ATSPI_RELATION_CONTROLLER_FOR); + AtspiAccessible *relation = flat_navi_get_object_in_relation(nd->current_obj, ATSPI_RELATION_CONTROLLER_FOR); if(relation) obj = relation; else - obj = current_obj; + obj = nd->current_obj; if (!obj) return EINA_FALSE; @@ -2200,13 +2229,13 @@ static Eina_Bool _has_value(void) return EINA_FALSE; } -static Eina_Bool _is_enabled(void) +static Eina_Bool _is_enabled(Navigator_Data *nd) { - if (!current_obj) { + if (nd->current_obj == NULL) { return EINA_FALSE; } - AtspiAccessible *relation = flat_navi_get_object_in_relation(current_obj, ATSPI_RELATION_CONTROLLER_FOR); + AtspiAccessible *relation = flat_navi_get_object_in_relation(nd->current_obj, ATSPI_RELATION_CONTROLLER_FOR); if(relation) { Eina_Bool ret = _widget_has_state(relation, ATSPI_STATE_ENABLED); @@ -2215,7 +2244,7 @@ static Eina_Bool _is_enabled(void) } else { - return _widget_has_state(current_obj, ATSPI_STATE_ENABLED); + return _widget_has_state(nd->current_obj, ATSPI_STATE_ENABLED); } } @@ -2324,10 +2353,20 @@ void end_scroll(int x, int y) #endif } -static void _move_slider(Gesture_Info * gi) +static void _move_slider(Navigator_Data *nd, Gesture_Info *gi) { DEBUG("ONE FINGER DOUBLE TAP AND HOLD"); + if (nd == NULL) { + ERROR("NULL context"); + return; + } + + if (gi == NULL) { + ERROR("NULL gesture"); + return; + } + if (!context) { ERROR("No navigation context created"); return; @@ -2336,11 +2375,11 @@ static void _move_slider(Gesture_Info * gi) AtspiAccessible *obj = NULL; AtspiComponent *comp = NULL; AtspiRect *rect = NULL; - obj = current_obj; + obj = nd->current_obj; if (!obj) { DEBUG("no object"); - prepared = false; + nd->prepared = false; return; } @@ -2350,7 +2389,7 @@ static void _move_slider(Gesture_Info * gi) if (!_is_slider(obj)) { DEBUG("Object is not a slider"); - prepared = false; + nd->prepared = false; if(relation) g_object_unref(relation); return; @@ -2358,7 +2397,7 @@ static void _move_slider(Gesture_Info * gi) if (!_widget_has_state(obj, ATSPI_STATE_ENABLED)) { DEBUG("Slider is disabled"); - prepared = false; + nd->prepared = false; if(relation) g_object_unref(relation); return; @@ -2368,7 +2407,7 @@ static void _move_slider(Gesture_Info * gi) comp = atspi_accessible_get_component_iface(obj); if (!comp) { ERROR("that slider do not have component interface"); - prepared = false; + nd->prepared = false; if(relation) g_object_unref(relation); return; @@ -2382,28 +2421,28 @@ static void _move_slider(Gesture_Info * gi) } if (gi->state == 1) { - counter++; - DEBUG("SCROLLING but not meet counter:%d", counter); - if (counter >= GESTURE_LIMIT) { - counter = 0; + nd->counter++; + DEBUG("SCROLLING but not meet counter:%d", nd->counter); + if (nd->counter >= GESTURE_LIMIT) { + nd->counter = 0; DEBUG("Scroll on point %d %d", gi->x_end, gi->y_end); - if (last_pos.x != -1) { - if (last_pos.x > gi->x_end) - _value_dec(); + if (nd->last_pos.x != -1) { + if (nd->last_pos.x > gi->x_end) + _value_dec(nd); else - _value_inc(); + _value_inc(nd); } - last_pos.x = gi->x_end; - last_pos.y = gi->y_end; + nd->last_pos.x = gi->x_end; + nd->last_pos.y = gi->y_end; } } if (gi->state == 2) { DEBUG("state == 2"); - prepared = false; + nd->prepared = false; _highlight_on_slider(EINA_FALSE); - last_pos.x = -1; - last_pos.y = -1; + nd->last_pos.x = -1; + nd->last_pos.y = -1; } if(relation) @@ -2499,6 +2538,13 @@ static Eina_Bool _check_access_object_internal(Highlight_Type h_type) static void on_gesture_detected(void *data, const Eldbus_Message *msg) { + Navigator_Data *nd = (Navigator_Data *)data; + + if (nd == NULL) { + ERROR("NULL context"); + return; + } + #ifdef X11_ENABLED Ecore_X_Window keyboard_win; #else @@ -2522,16 +2568,16 @@ static void on_gesture_detected(void *data, const Eldbus_Message *msg) DEBUG("Incoming gesture name is %s : %d %d %d %d %d", _gesture_enum_to_string(info->type), info->x_beg, info->y_beg, info->x_end, info->y_end, info->state); - _on_auto_review_stop(); + _on_auto_review_stop(nd); if (info->type == ONE_FINGER_SINGLE_TAP && info->state == 3) { DEBUG("One finger single tap aborted"); - prepared = true; + nd->prepared = true; if (sound_feedback) smart_notification(LONG_PRESS_NOTIFICATION_EVENT, 0, 0); - AtspiAccessible *relation = flat_navi_get_object_in_relation(current_obj, ATSPI_RELATION_CONTROLLER_FOR); + AtspiAccessible *relation = flat_navi_get_object_in_relation(nd->current_obj, ATSPI_RELATION_CONTROLLER_FOR); if(relation) { if (_is_slider(relation)) @@ -2541,25 +2587,25 @@ static void on_gesture_detected(void *data, const Eldbus_Message *msg) } else { - if (_is_slider(current_obj)) + if (_is_slider(nd->current_obj)) _highlight_on_slider(EINA_TRUE); - _send_highlighted_object_info(current_obj); + _send_highlighted_object_info(nd->current_obj); } } switch (info->type) { case ONE_FINGER_HOVER: - if (prepared) { + if (nd->prepared) { DEBUG("Prepare to move slider"); - _move_slider(info); + _move_slider(nd, info); } else { - if (_last_hover_event_time < 0) - _last_hover_event_time = info->event_time; - //info->event_time and _last_hover_event_time contain timestamp in ms. + if (nd->last_hover_event_time < 0) + nd->last_hover_event_time = info->event_time; + //info->event_time and last_hover_event_time contain timestamp in ms. //RETURN so we do not handle all incoming event - if ((info->event_time - _last_hover_event_time) < ONGOING_HOVER_GESTURE_INTERPRETATION_INTERVAL && info->state == 1) + if ((info->event_time - nd->last_hover_event_time) < ONGOING_HOVER_GESTURE_INTERPRETATION_INTERVAL && info->state == 1) return; - _last_hover_event_time = info->state != 1 ? -1 : info->event_time; + nd->last_hover_event_time = info->state != 1 ? -1 : info->event_time; #if defined(ELM_ACCESS_KEYBOARD) && defined(X11_ENABLED) keyboard_win = top_window_get(info->x_end, info->y_end); if (keyboard_win && ecore_x_e_virtual_keyboard_get(keyboard_win)) { @@ -2574,41 +2620,41 @@ static void on_gesture_detected(void *data, const Eldbus_Message *msg) break; } #endif - _focus_widget(info); + _focus_widget(nd, info); } break; case TWO_FINGERS_HOVER: - _widget_scroll(info); + _widget_scroll(nd, info); break; case ONE_FINGER_FLICK_LEFT: if (_check_access_object_internal(HIGHLIGHT_PREV)) break; - _focus_prev(); + _focus_prev(nd); if (_is_index_item()) - _activate_widget(); + _activate_widget(nd); break; case ONE_FINGER_FLICK_RIGHT: if (_check_access_object_internal(HIGHLIGHT_NEXT)) break; - _focus_next(); + _focus_next(nd); if (_is_index_item()) - _activate_widget(); + _activate_widget(nd); break; case ONE_FINGER_FLICK_UP: if (_is_active_entry()) - _caret_move_backward(); - else if (_has_value() && _is_enabled()) - _value_inc(); + _caret_move_backward(nd); + else if (_has_value(nd) && _is_enabled(nd)) + _value_inc(nd); else - _focus_prev(); + _focus_prev(nd); break; case ONE_FINGER_FLICK_DOWN: if (_is_active_entry()) - _caret_move_forward(); - else if (_has_value() && _is_enabled()) - _value_dec(); + _caret_move_forward(nd); + else if (_has_value(nd) && _is_enabled(nd)) + _value_dec(nd); else - _focus_next(); + _focus_next(nd); break; case ONE_FINGER_SINGLE_TAP: #if defined(ELM_ACCESS_KEYBOARD) && defined(X11_ENABLED) @@ -2625,8 +2671,8 @@ static void on_gesture_detected(void *data, const Eldbus_Message *msg) break; } #endif - if (!prepared) - _focus_widget(info); + if (!nd->prepared) + _focus_widget(nd, info); break; case ONE_FINGER_DOUBLE_TAP: #if defined(ELM_ACCESS_KEYBOARD) && defined(X11_ENABLED) @@ -2643,7 +2689,7 @@ static void on_gesture_detected(void *data, const Eldbus_Message *msg) break; } #endif - _activate_widget(); + _activate_widget(nd); break; case TWO_FINGERS_SINGLE_TAP: _set_pause(); @@ -2657,10 +2703,10 @@ static void on_gesture_detected(void *data, const Eldbus_Message *msg) #endif break; case THREE_FINGERS_SINGLE_TAP: - _review_from_top(); + _review_from_top(nd); break; case THREE_FINGERS_DOUBLE_TAP: - _review_from_current(); + _review_from_current(nd); break; case THREE_FINGERS_FLICK_DOWN: _quickpanel_change_state(QUICKPANEL_DOWN); @@ -2669,22 +2715,22 @@ static void on_gesture_detected(void *data, const Eldbus_Message *msg) _quickpanel_change_state(QUICKPANEL_UP); break; case ONE_FINGER_FLICK_LEFT_RETURN: - _direct_scroll_back(); + _direct_scroll_back(nd); break; case ONE_FINGER_FLICK_RIGHT_RETURN: - _direct_scroll_forward(); + _direct_scroll_forward(nd); break; case ONE_FINGER_FLICK_UP_RETURN: if (_is_active_entry()) - _caret_move_beg(); + _caret_move_beg(nd); else - _direct_scroll_to_first(); + _direct_scroll_to_first(nd); break; case ONE_FINGER_FLICK_DOWN_RETURN: if (_is_active_entry()) - _caret_move_end(); + _caret_move_end(nd); else - _direct_scroll_to_last(); + _direct_scroll_to_last(nd); break; default: DEBUG("Gesture type %d not handled in switch", info->type); @@ -2696,6 +2742,13 @@ static void on_gesture_detected(void *data, const Eldbus_Message *msg) static void _view_content_changed(AtspiAccessible * root, void *user_data) { + Navigator_Data *nd = (Navigator_Data *)user_data; + + if (nd == NULL) { + ERROR("NULL context"); + return; + } + AtspiRole role = -1; if (flat_navi_is_valid(context, root)) @@ -2713,7 +2766,7 @@ static void _view_content_changed(AtspiAccessible * root, void *user_data) if(role == ATSPI_ROLE_PAGE_TAB || //add more roles... role == ATSPI_ROLE_PAGE_TAB_LIST) { - _current_highlight_object_set(flat_navi_context_current_get(context), HIGHLIGHT_FIRST); + _current_highlight_object_set(nd, flat_navi_context_current_get(context), HIGHLIGHT_FIRST); } else { @@ -2728,7 +2781,7 @@ static void _view_content_changed(AtspiAccessible * root, void *user_data) break; case ATSPI_ROLE_POPUP_MENU: case ATSPI_ROLE_DIALOG : - _current_highlight_object_set(flat_navi_context_current_get(context), HIGHLIGHT_FIRST); + _current_highlight_object_set(nd, flat_navi_context_current_get(context), HIGHLIGHT_FIRST); break; default : break; @@ -2740,10 +2793,12 @@ static void _view_content_changed(AtspiAccessible * root, void *user_data) static void _new_highlighted_obj_changed(AtspiAccessible * new_highlighted_obj, void *user_data) { DEBUG("context: %p, current: %p, new_highlighted_obj: %p", context, flat_navi_context_current_get(context), new_highlighted_obj); + Service_Data *service_data = get_pointer_to_service_data_struct(); + Navigator_Data *nd = service_data->navigator_data; if (context && flat_navi_context_current_get(context) != new_highlighted_obj) { flat_navi_context_current_set(context, g_object_ref(new_highlighted_obj)); - current_obj = new_highlighted_obj; - current_comp = atspi_accessible_get_component_iface(new_highlighted_obj); + nd->current_obj = new_highlighted_obj; + nd->current_comp = atspi_accessible_get_component_iface(new_highlighted_obj); } } @@ -2798,16 +2853,23 @@ static void on_window_activate(void *data, AtspiAccessible * window) { DEBUG("START"); - if (top_window) - app_tracker_callback_unregister(top_window, _view_content_changed, NULL); + Navigator_Data *nd = (Navigator_Data *)data; + + if (nd == NULL) { + ERROR("NULL context"); + return; + } + + if (nd->top_window) + app_tracker_callback_unregister(nd->top_window, _view_content_changed, nd); if (window) { DEBUG("Window name: %s", atspi_accessible_get_name(window, NULL)); // TODO: modal descendant of window should be used (if exists) otherwise window AtspiAccessible *modal_descendant = _get_modal_descendant(window); - app_tracker_callback_register(modal_descendant ? modal_descendant : window, _view_content_changed, NULL); - _view_content_changed(modal_descendant ? modal_descendant : window, NULL); - top_window = modal_descendant ? modal_descendant : window; + app_tracker_callback_register(modal_descendant ? modal_descendant : window, _view_content_changed, nd); + _view_content_changed(modal_descendant ? modal_descendant : window, nd); + nd->top_window = modal_descendant ? modal_descendant : window; g_object_unref(modal_descendant); } else { flat_navi_context_free(context); @@ -2839,40 +2901,74 @@ void navigator_gestures_tracker_register(GestureCB gesture_cb, void *data) return; } -void navigator_init(void) +Navigator_Data *navigator_init(Service_Data *sd) { DEBUG("START"); + if (sd == NULL) { + ERROR("NULL context"); + return NULL; + } + + Navigator_Data *nd = calloc(1, sizeof(Navigator_Data)); + + if (nd == NULL) { + ERROR("calloc(1,%d) failed", sizeof(Navigator_Data)); + return NULL; + } + + nd->gesture_start_p = (point_t) { .x = -1, .y = -1}; + nd->last_focus = (point_t) { .x = -1, .y = -1}; + nd->last_pos = (point_t) { .x = -1, .y = -1}; + nd->last_hover_event_time = -1; + nd->focused_object = NULL; + nd->auto_review_on = false; + set_utterance_cb(_on_utterance); - navigator_gestures_tracker_register(on_gesture_detected, NULL); + navigator_gestures_tracker_register(on_gesture_detected, nd); // register on active_window dbus_gesture_adapter_init(); app_tracker_init(); app_tracker_new_obj_highlighted_callback_register(_new_highlighted_obj_changed); window_tracker_init(); - window_tracker_register(on_window_activate, NULL); + window_tracker_register(on_window_activate, nd); window_tracker_active_window_request(); smart_notification_init(); #ifndef SCREEN_READER_TV system_notifications_init(); #endif + + return nd; } -void navigator_shutdown(void) +void navigator_shutdown(Service_Data *sd) { + if (sd == NULL) { + ERROR("NULL context"); + return; + } + + if (sd->navigator_data == NULL) { + ERROR("NULL navigator context"); + return; + } + GError *err = NULL; - if (current_obj) { - AtspiComponent *comp = atspi_accessible_get_component_iface(current_obj); + + if (sd->navigator_data->current_obj != NULL) { + AtspiComponent *comp = atspi_accessible_get_component_iface(sd->navigator_data->current_obj); if (comp) { atspi_component_clear_highlight(comp, &err); GERROR_CHECK(err); } } + if (context) { flat_navi_context_free(context); context = NULL; } + dbus_gesture_adapter_shutdown(); app_tracker_shutdown(); window_tracker_shutdown(); @@ -2880,4 +2976,6 @@ void navigator_shutdown(void) #ifndef SCREEN_READER_TV system_notifications_shutdown(); #endif + + free(sd->navigator_data); }