cleanup
[profile/tv/apps/native/screen-reader.git] / src / navigator.c
1 #include <math.h>
2 #include <atspi/atspi.h>
3 #include "logger.h"
4 #include "navigator.h"
5 #include "window_tracker.h"
6 #include "keyboard_tracker.h"
7 #include "pivot_chooser.h"
8 #include "structural_navi.h"
9 #include "object_cache.h"
10 #include "flat_navi.h"
11 #include "app_tracker.h"
12
13 #define QUICKPANEL_DOWN TRUE
14 #define QUICKPANEL_UP FALSE
15
16 #define DISTANCE_NB 8
17
18 #define DEBUG_MODE
19
20 #define GERROR_CHECK(error)\
21   if (error)\
22    {\
23      ERROR("Error_log:%s",error->message);\
24      g_error_free(error);\
25      error = NULL;\
26    }
27
28 static AtspiAccessible *top_window;
29 static gboolean _window_cache_builded;
30 static FlatNaviContext *context;
31
32 static void
33 _current_highlight_object_set(AtspiAccessible *obj)
34 {
35    //TODO
36    //speak virtually focused widget
37 }
38
39 void test_debug(AtspiAccessible *current_widget)
40 {
41     int jdx;
42     int count_child;
43     gchar *role;
44     GError *err = NULL;
45     AtspiAccessible *child_iter = NULL;
46     AtspiAccessible *parent = atspi_accessible_get_parent(current_widget, &err);
47     GERROR_CHECK(err)
48
49     if(!parent)
50       return;
51     count_child = atspi_accessible_get_child_count(parent, &err);
52     GERROR_CHECK(err)
53     DEBUG("Total childs in parent: %d\n", count_child);
54     if(!count_child)
55         return;
56
57     for(jdx = 0; jdx < count_child; jdx++)
58     {
59         child_iter = atspi_accessible_get_child_at_index(parent, jdx, &err);
60         GERROR_CHECK(err)
61
62         if(current_widget == child_iter)
63           {
64             role = atspi_accessible_get_role_name(parent, &err);
65             DEBUG("Childen found in parent: %s at index: %d\n", role, jdx);
66           }
67         else
68           {
69             role = atspi_accessible_get_role_name(parent, &err);
70             DEBUG("Childen not found in parent: %s at index: %d\n", role, jdx);
71           }
72         g_free(role);
73         GERROR_CHECK(err)
74     }
75 }
76
77 static void _focus_next(void)
78 {
79    AtspiAccessible *obj;
80    if (!context)
81      {
82         ERROR("No navigation context created");
83         return;
84      }
85    obj = flat_navi_context_next(context);
86    // try next line
87    if (!obj)
88         obj = flat_navi_context_line_next(context);
89    // try 'cycle' objects in context
90    if (!obj)
91      {
92         flat_navi_context_line_first(context);
93         obj = flat_navi_context_first(context);
94      }
95    if (obj)
96      _current_highlight_object_set(obj);
97    else
98      DEBUG("Next widget not found. Abort");
99 }
100
101 static void _focus_prev(void)
102 {
103    AtspiAccessible *obj;
104    if (!context)
105      {
106         ERROR("No navigation context created");
107         return;
108      }
109    obj = flat_navi_context_prev(context);
110    // try previous line
111    if (!obj)
112      {
113         obj = flat_navi_context_line_prev(context);
114         if (obj)
115            obj = flat_navi_context_last(context);
116      }
117    // try 'cycle' objects in context
118    if (!obj)
119      {
120         flat_navi_context_line_last(context);
121         obj = flat_navi_context_last(context);
122      }
123    if (obj)
124      _current_highlight_object_set(obj);
125    else
126      DEBUG("Previous widget not found. Abort");
127 }
128
129 static void
130 _on_cache_builded(void *data)
131 {
132    DEBUG("Cache building");
133    _window_cache_builded = TRUE;
134    AtspiAccessible *pivot = NULL;
135    if (context)
136      {
137         pivot = flat_navi_context_current_get(context);
138         flat_navi_context_free(context);
139      }
140    context = flat_navi_context_create(top_window);
141
142    // try to set previous object in new context
143    if (flat_navi_context_current_set(context, pivot))
144      _current_highlight_object_set(pivot);
145    else
146      _current_highlight_object_set(flat_navi_context_current_get(context));
147    DEBUG("Cache building finished");
148 }
149
150 static void
151 _view_content_changed(AppTrackerEventType type, void *user_data)
152 {
153    DEBUG("View content changed");
154    _window_cache_builded = FALSE;
155    if (top_window)
156       object_cache_build_async(top_window, 5, _on_cache_builded, NULL);
157 }
158
159 static void on_window_activate(void *data, AtspiAccessible *window)
160 {
161    gchar *name;
162    DEBUG("... on window activate ...");
163
164    app_tracker_callback_unregister(top_window, APP_TRACKER_EVENT_VIEW_CHANGED, _view_content_changed, NULL);
165
166    if(window)
167    {
168       app_tracker_callback_register(window, APP_TRACKER_EVENT_VIEW_CHANGED, _view_content_changed, NULL);
169       name = atspi_accessible_get_name(window, NULL);
170       DEBUG("Window name: %s", name);
171       _window_cache_builded = FALSE;
172       object_cache_build_async(window, 5, _on_cache_builded, NULL);
173       g_free(name);
174    }
175    else
176    {
177        ERROR("No top window found!");
178    }
179    top_window = window;
180 }
181
182 void kb_tracker (void *data, Key k)
183 {
184    switch(k)
185    {
186       case KEY_LEFT:
187           _focus_prev();
188           break;
189       case KEY_RIGHT:
190           _focus_next();
191           break;
192       default:
193           DEBUG("Key %d not supported \n", k);
194    }
195 }
196
197 void navigator_init(void)
198 {
199    window_tracker_init();
200    window_tracker_register(on_window_activate, NULL);
201    window_tracker_active_window_request();
202    app_tracker_init();
203    keyboard_tracker_init();
204    keyboard_tracker_register(kb_tracker, NULL);
205 }
206
207 void navigator_shutdown(void)
208 {
209    if (context)
210      {
211         flat_navi_context_free(context);
212         context = NULL;
213      }
214    object_cache_shutdown();
215    app_tracker_shutdown();
216    window_tracker_shutdown();
217    keyboard_tracker_shutdown();
218 }