mobile-lua: add additional LABELLED_BY relation
[profile/tv/apps/native/screen-reader.git] / src / navigator.c
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
3  *
4  * Licensed under the Flora License, Version 1.1 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://floralicense.org/license/
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #define _GNU_SOURCE
18 #include <stdio.h>
19 #ifdef X11_ENABLED
20 #include <Ecore_X.h>
21 #else
22 #include <Ecore_Wayland.h>
23 #endif
24 #include <Ecore.h>
25 #include <math.h>
26 #include <atspi/atspi.h>
27 #include "logger.h"
28 #include "navigator.h"
29 #include "window_tracker.h"
30 #include "keyboard_tracker.h"
31 #include "flat_navi.h"
32 #include "app_tracker.h"
33 #include "smart_notification.h"
34 #include "screen_reader_system.h"
35 #include "screen_reader_haptic.h"
36 #include "screen_reader_tts.h"
37 #include "screen_reader_gestures.h"
38 #include "dbus_gesture_adapter.h"
39 #include "elm_access_adapter.h"
40 #include "lua_engine.h"
41
42 #define QUICKPANEL_DOWN TRUE
43 #define QUICKPANEL_UP FALSE
44
45 #define DISTANCE_NB 8
46 #define MENU_ITEM_TAB_INDEX_SIZE 16
47 #define HOVERSEL_TRAIT_SIZE 200
48 #define TTS_MAX_TEXT_SIZE  2000
49 #define GESTURE_LIMIT 10
50
51 //Timeout in ms which will be used as interval for handling ongoing
52 //hoved gesture updates. It is introduced to improve performance.
53 //Even if user makes many mouse move events within hover gesture
54 //only 5 highlight updates a second will be performed. Else we will
55 //highly pollute dbus bus and and decrease highlight performance.
56 #define ONGOING_HOVER_GESTURE_INTERPRETATION_INTERVAL 200
57
58 #define DEBUG_MODE
59
60 #define GERROR_CHECK(error)\
61   if (error)\
62    {\
63      ERROR("Error_log:%s",error->message);\
64      g_error_free(error);\
65      error = NULL;\
66    }
67
68 static void on_window_activate(void *data, AtspiAccessible * window);
69
70 typedef struct {
71         int x, y;
72 } last_focus_t;
73
74 static last_focus_t gesture_start_p = { -1, -1 };
75 static last_focus_t last_focus = { -1, -1 };
76
77 static AtspiAccessible *current_obj;
78 static AtspiComponent *current_comp = NULL;
79 static AtspiAccessible *top_window;
80 static FlatNaviContext *context;
81 static bool prepared = false;
82 static int counter = 0;
83 int _last_hover_event_time = -1;
84
85 static struct {
86         AtspiAccessible *focused_object;
87         bool auto_review_on;
88 } s_auto_review = {
89 .focused_object = NULL,.auto_review_on = false};
90
91 static bool _widget_has_state(AtspiAccessible * obj, AtspiStateType type)
92 {
93         Eina_Bool ret = EINA_FALSE;
94         AtspiStateSet *st = atspi_accessible_get_state_set(obj);
95         if (atspi_state_set_contains(st, type))
96                 ret = EINA_TRUE;
97         g_object_unref(st);
98         return ret;
99 }
100
101 char *state_to_char(AtspiStateType state)
102 {
103         switch (state) {
104         case ATSPI_STATE_INVALID:
105                 return strdup("ATSPI_STATE_INVALID");
106         case ATSPI_STATE_ACTIVE:
107                 return strdup("ATSPI_STATE_ACTIVE");
108         case ATSPI_STATE_ARMED:
109                 return strdup("ATSPI_STATE_ARMED");
110         case ATSPI_STATE_BUSY:
111                 return strdup("ATSPI_STATE_BUSY");
112         case ATSPI_STATE_CHECKED:
113                 return strdup("ATSPI_STATE_CHECKED");
114         case ATSPI_STATE_COLLAPSED:
115                 return strdup("ATSPI_STATE_COLLAPSED");
116         case ATSPI_STATE_DEFUNCT:
117                 return strdup("ATSPI_STATE_DEFUNCT");
118         case ATSPI_STATE_EDITABLE:
119                 return strdup("ATSPI_STATE_EDITABLE");
120         case ATSPI_STATE_ENABLED:
121                 return strdup("ATSPI_STATE_ENABLED");
122         case ATSPI_STATE_EXPANDABLE:
123                 return strdup("ATSPI_STATE_EXPANDABLE");
124         case ATSPI_STATE_EXPANDED:
125                 return strdup("ATSPI_STATE_EXPANDED");
126         case ATSPI_STATE_FOCUSABLE:
127                 return strdup("ATSPI_STATE_FOCUSABLE");
128         case ATSPI_STATE_FOCUSED:
129                 return strdup("ATSPI_STATE_FOCUSED");
130         case ATSPI_STATE_HAS_TOOLTIP:
131                 return strdup("ATSPI_STATE_HAS_TOOLTIP");
132         case ATSPI_STATE_HORIZONTAL:
133                 return strdup("ATSPI_STATE_HORIZONTAL");
134         case ATSPI_STATE_ICONIFIED:
135                 return strdup("ATSPI_STATE_ICONIFIED");
136         case ATSPI_STATE_MULTI_LINE:
137                 return strdup("ATSPI_STATE_MULTI_LINE");
138         case ATSPI_STATE_MULTISELECTABLE:
139                 return strdup("ATSPI_STATE_MULTISELECTABLE");
140         case ATSPI_STATE_OPAQUE:
141                 return strdup("ATSPI_STATE_OPAQUE");
142         case ATSPI_STATE_PRESSED:
143                 return strdup("ATSPI_STATE_PRESSED");
144         case ATSPI_STATE_RESIZABLE:
145                 return strdup("ATSPI_STATE_RESIZABLE");
146         case ATSPI_STATE_SELECTABLE:
147                 return strdup("ATSPI_STATE_SELECTABLE");
148         case ATSPI_STATE_SELECTED:
149                 return strdup("ATSPI_STATE_SELECTED");
150         case ATSPI_STATE_SENSITIVE:
151                 return strdup("ATSPI_STATE_SENSITIVE");
152         case ATSPI_STATE_SHOWING:
153                 return strdup("ATSPI_STATE_SHOWING");
154         case ATSPI_STATE_SINGLE_LINE:
155                 return strdup("ATSPI_STATE_SINGLE_LINE");
156         case ATSPI_STATE_STALE:
157                 return strdup("ATSPI_STATE_STALE");
158         case ATSPI_STATE_TRANSIENT:
159                 return strdup("ATSPI_STATE_TRANSIENT");
160         case ATSPI_STATE_VERTICAL:
161                 return strdup("ATSPI_STATE_VERTICAL");
162         case ATSPI_STATE_VISIBLE:
163                 return strdup("ATSPI_STATE_VISIBLE");
164         case ATSPI_STATE_MANAGES_DESCENDANTS:
165                 return strdup("ATSPI_STATE_MANAGES_DESCENDANTS");
166         case ATSPI_STATE_INDETERMINATE:
167                 return strdup("ATSPI_STATE_INDETERMINATE");
168         case ATSPI_STATE_REQUIRED:
169                 return strdup("ATSPI_STATE_REQUIRED");
170         case ATSPI_STATE_TRUNCATED:
171                 return strdup("ATSPI_STATE_TRUNCATED");
172         case ATSPI_STATE_ANIMATED:
173                 return strdup("ATSPI_STATE_ANIMATED");
174         case ATSPI_STATE_INVALID_ENTRY:
175                 return strdup("ATSPI_STATE_INVALID_ENTRY");
176         case ATSPI_STATE_SUPPORTS_AUTOCOMPLETION:
177                 return strdup("ATSPI_STATE_SUPPORTS_AUTOCOMPLETION");
178         case ATSPI_STATE_SELECTABLE_TEXT:
179                 return strdup("ATSPI_STATE_SELECTABLE_TEXT");
180         case ATSPI_STATE_IS_DEFAULT:
181                 return strdup("ATSPI_STATE_IS_DEFAULT");
182         case ATSPI_STATE_VISITED:
183                 return strdup("ATSPI_STATE_VISITED");
184         case ATSPI_STATE_CHECKABLE:
185                 return strdup("ATSPI_STATE_CHECKABLE");
186         case ATSPI_STATE_HAS_POPUP:
187                 return strdup("ATSPI_STATE_HAS_POPUP");
188         case ATSPI_STATE_READ_ONLY:
189                 return strdup("ATSPI_STATE_READ_ONLY");
190         case ATSPI_STATE_LAST_DEFINED:
191                 return strdup("ATSPI_STATE_LAST_DEFINED");
192         case ATSPI_STATE_MODAL:
193                 return strdup("ATSPI_STATE_MODAL");
194         case ATSPI_STATE_HIGHLIGHTED:
195                 return strdup("ATSPI_STATE_HIGHLIGHTED");
196         case ATSPI_STATE_HIGHLIGHTABLE:
197                 return strdup("ATSPI_STATE_HIGHLIGHTABLE");
198         default:
199                 return strdup("\0");
200         }
201
202 }
203
204 static void display_info_about_object(AtspiAccessible * obj, bool display_parent_info)
205 {
206         if(!obj)
207         {
208                 return;
209         }
210
211         DEBUG("START");
212         DEBUG("------------------------");
213         gchar *name = atspi_accessible_get_name(obj, NULL);
214         gchar *role = atspi_accessible_get_localized_role_name(obj, NULL);
215         gchar *description = atspi_accessible_get_description(obj, NULL);
216         char *state_name = NULL;
217         AtspiStateSet *st = atspi_accessible_get_state_set(obj);
218         GArray *states = atspi_state_set_get_states(st);
219         AtspiComponent *comp = atspi_accessible_get_component_iface(obj);
220         AtspiValue *value = atspi_accessible_get_value_iface(obj);
221         AtspiRect *rect_screen = atspi_component_get_extents(comp, ATSPI_COORD_TYPE_SCREEN, NULL);
222         AtspiRect *rect_win = atspi_component_get_extents(comp, ATSPI_COORD_TYPE_WINDOW, NULL);
223
224         if(display_parent_info) {
225                 AtspiAccessible *parent = atspi_accessible_get_parent(obj, NULL);
226                 display_info_about_object(parent, false);
227                 g_object_unref(parent);
228         }
229
230         DEBUG("NAME:%s", name);
231         DEBUG("ROLE:%s", role);
232         DEBUG("DESCRIPTION:%s", description);
233         DEBUG("CHILDS:%d", atspi_accessible_get_child_count(obj, NULL));
234         DEBUG("HIGHLIGHT_INDEX:%d", atspi_component_get_highlight_index(comp, NULL));
235         DEBUG("INDEX IN PARENT:%d", atspi_accessible_get_index_in_parent(obj, NULL));
236         if (value) {
237                 DEBUG("VALUE:%f", atspi_value_get_current_value(value, NULL));
238                 DEBUG("VALUE MAX:%f", atspi_value_get_maximum_value(value, NULL));
239                 DEBUG("VALUE MIN:%f", atspi_value_get_minimum_value(value, NULL));
240                 g_object_unref(value);
241         }
242         DEBUG("STATES:");
243         int a;
244         AtspiStateType stat;
245         for (a = 0; states && (a < states->len); ++a) {
246                 stat = g_array_index(states, AtspiStateType, a);
247                 state_name = state_to_char(stat);
248                 DEBUG("   %s", state_name);
249                 free(state_name);
250         }
251         g_array_free(states, 0);
252         DEBUG("LOCALE:%s", atspi_accessible_get_object_locale(obj, NULL));
253         DEBUG("SIZE ON SCREEN, width:%d, height:%d", rect_screen->width, rect_screen->height);
254         DEBUG("POSITION ON SCREEN: x:%d y:%d", rect_screen->x, rect_screen->y);
255         DEBUG("SIZE ON WIN, width:%d, height:%d", rect_win->width, rect_win->height);
256         DEBUG("POSITION ON WIN: x:%d y:%d", rect_win->x, rect_win->y);
257         DEBUG("INTERFACES:");
258         GArray *ifaces = atspi_accessible_get_interfaces(obj);
259         for (a = 0; ifaces && (a < ifaces->len); ++a) {
260                 gchar * interface_name = g_array_index(ifaces, gchar *, a);
261                 DEBUG("   %s", interface_name);
262                 g_free(interface_name);
263         }
264         if (ifaces)
265                 g_array_free(ifaces, FALSE);
266
267         DEBUG("------------------------");
268         DEBUG("END");
269         g_free(name);
270         g_free(role);
271         g_free(description);
272 }
273
274 static char *generate_what_to_read(AtspiAccessible * obj)
275 {
276         return lua_engine_describe_object(obj);
277 }
278
279 static void _current_highlight_object_set(AtspiAccessible * obj)
280 {
281         DEBUG("START");
282         GError *err = NULL;
283         gchar *role = NULL;
284
285         if (!obj) {
286                 DEBUG("Clearing highlight object");
287                 current_obj = NULL;
288                 if (current_comp) {
289                         atspi_component_clear_highlight(current_comp, &err);
290                         g_object_ref(current_comp);
291                         current_comp = NULL;
292                 }
293
294                 return;
295         }
296         if (current_obj == obj) {
297                 DEBUG("Object already highlighted");
298                 DEBUG("Object name:%s", atspi_accessible_get_name(obj, NULL));
299                 return;
300         }
301         if (obj && ATSPI_IS_COMPONENT(obj)) {
302                 DEBUG("OBJ WITH COMPONENT");
303                 AtspiComponent *comp = atspi_accessible_get_component_iface(obj);
304                 if (!comp) {
305                         GError *err = NULL;
306                         role = atspi_accessible_get_role_name(obj, &err);
307                         ERROR("AtspiComponent *comp NULL, [%s]", role);
308                         GERROR_CHECK(err);
309                         g_free(role);
310                         return;
311                 }
312                 if (current_comp) {
313                         atspi_component_clear_highlight(current_comp, &err);
314                 }
315                 atspi_component_grab_highlight(comp, &err);
316                 current_comp = comp;
317                 GERROR_CHECK(err)
318
319                 Eina_Bool is_paused = tts_pause_get();
320                 if (is_paused) {
321                         tts_stop_set();
322                         tts_pause_set(EINA_FALSE);
323                 }
324                 current_obj = obj;
325                 char *text_to_speak = NULL;
326                 text_to_speak = generate_what_to_read(obj);
327                 DEBUG("SPEAK:%s", text_to_speak);
328
329                 tts_speak(text_to_speak, EINA_TRUE);
330                 g_free(text_to_speak);
331         } else
332                 DEBUG("Unable to highlight on object");
333         DEBUG("END");
334 }
335
336 void test_debug(AtspiAccessible * current_widget)
337 {
338         int jdx;
339         int count_child;
340         gchar *role;
341         GError *err = NULL;
342         AtspiAccessible *child_iter = NULL;
343         AtspiAccessible *parent = atspi_accessible_get_parent(current_widget, &err);
344         GERROR_CHECK(err)
345
346                 if (!parent)
347                 return;
348         count_child = atspi_accessible_get_child_count(parent, &err);
349         GERROR_CHECK(err)
350                 DEBUG("Total childs in parent: %d\n", count_child);
351         if (!count_child)
352         {
353                 g_object_unref(parent);
354                 return;
355         }
356
357         for (jdx = 0; jdx < count_child; jdx++) {
358                 child_iter = atspi_accessible_get_child_at_index(parent, jdx, &err);
359                 GERROR_CHECK(err)
360
361                         if (current_widget == child_iter) {
362                         role = atspi_accessible_get_role_name(parent, &err);
363                         DEBUG("Childen found in parent: %s at index: %d\n", role, jdx);
364                 } else {
365                         role = atspi_accessible_get_role_name(parent, &err);
366                         DEBUG("Childen not found in parent: %s at index: %d\n", role, jdx);
367                 }
368                 g_free(role);
369                 GERROR_CHECK(err)
370         }
371         g_object_unref(parent);
372 }
373
374 static void _focus_widget(Gesture_Info * info)
375 {
376         DEBUG("START");
377
378         if ((last_focus.x == info->x_beg) && (last_focus.y == info->y_beg))
379                 return;
380
381         AtspiAccessible *obj = NULL;
382         if (flat_navi_context_current_at_x_y_set(context, info->x_beg, info->y_beg, &obj)) {
383                 last_focus.x = info->x_beg;
384                 last_focus.y = info->y_beg;
385                 _current_highlight_object_set(obj);
386         }
387
388         DEBUG("END");
389 }
390
391 static void _focus_next(void)
392 {
393         DEBUG("START");
394         AtspiAccessible *obj;
395         if (!context) {
396                 ERROR("No navigation context created");
397                 return;
398         }
399
400         obj = flat_navi_context_next(context);
401         if (obj)
402                 _current_highlight_object_set(obj);
403         else
404                 DEBUG("Next widget not found. Abort");
405         DEBUG("END");
406 }
407
408 static void _focus_next_visible(void)
409 {
410         DEBUG("START");
411         AtspiAccessible *obj;
412         AtspiStateSet *ss = NULL;
413         Eina_Bool visible = EINA_FALSE;
414         if (!context) {
415                 ERROR("No navigation context created");
416                 return;
417         }
418
419         do {
420                 obj = flat_navi_context_next(context);
421                 // try 'cycle' objects in context
422                 if (obj) {
423                         ss = atspi_accessible_get_state_set(obj);
424                         visible = atspi_state_set_contains(ss, ATSPI_STATE_SHOWING);
425                         g_object_unref(ss);
426                 }
427         }
428         while (obj && !visible);
429
430         if (obj)
431                 _current_highlight_object_set(obj);
432         else
433                 DEBUG("Next widget not found. Abort");
434         DEBUG("END");
435 }
436
437 static void _focus_prev_visible(void)
438 {
439         AtspiAccessible *obj;
440         AtspiStateSet *ss = NULL;
441         Eina_Bool visible = EINA_FALSE;
442         if (!context) {
443                 ERROR("No navigation context created");
444                 return;
445         }
446         do {
447                 obj = flat_navi_context_prev(context);
448                 // try 'cycle' objects in context
449                 if (obj) {
450                         ss = atspi_accessible_get_state_set(obj);
451                         visible = atspi_state_set_contains(ss, ATSPI_STATE_SHOWING);
452                         g_object_unref(ss);
453                 }
454         }
455         while (obj && !visible);
456
457         if (obj)
458                 _current_highlight_object_set(obj);
459         else
460                 DEBUG("Previous widget not found. Abort");
461 }
462
463 static void _focus_prev(void)
464 {
465         AtspiAccessible *obj;
466         if (!context) {
467                 ERROR("No navigation context created");
468                 return;
469         }
470
471         obj = flat_navi_context_prev(context);
472         if (obj)
473                 _current_highlight_object_set(obj);
474         else
475                 DEBUG("Previous widget not found. Abort");
476 }
477
478 static void _caret_move_beg(void)
479 {
480         AtspiAccessible *current_widget = NULL;
481         AtspiText *text_interface;
482         gboolean ret;
483         GError *err = NULL;
484
485         if (!current_obj)
486                 return;
487
488         current_widget = current_obj;
489
490         text_interface = atspi_accessible_get_text_iface(current_widget);
491         if (text_interface) {
492                 ret = atspi_text_set_caret_offset(text_interface, 0, &err);
493                 GERROR_CHECK(err)
494                         if (ret) {
495                         DEBUG("Caret position increment done");
496                         gchar *text = atspi_text_get_text(text_interface, 0, 1, NULL);
497                         DEBUG("SPEAK:%s", text);
498                         tts_speak(text, EINA_TRUE);
499                         tts_speak(_("IDS_TEXT_BEGIN"), EINA_FALSE);
500                         g_free(text);
501                 } else {
502                         ERROR("Caret position increment error");
503                 }
504                 g_object_unref(text_interface);
505         } else
506                 ERROR("No text interface supported!");
507 }
508
509 static void _caret_move_end(void)
510 {
511         AtspiAccessible *current_widget = NULL;
512         AtspiText *text_interface;
513         gboolean ret;
514         GError *err = NULL;
515
516         if (!current_obj)
517                 return;
518
519         current_widget = current_obj;
520
521         text_interface = atspi_accessible_get_text_iface(current_widget);
522         if (text_interface) {
523                 int len = atspi_text_get_character_count(text_interface, NULL);
524                 ret = atspi_text_set_caret_offset(text_interface, len, &err);
525                 if (ret) {
526                         DEBUG("Caret position increment done");
527                         DEBUG("SPEAK:%s", _("IDS_TEXT_END"));
528                         tts_speak(_("IDS_TEXT_END"), EINA_TRUE);
529                 } else
530                         ERROR("Caret position to end error");
531                 g_object_unref(text_interface);
532         }
533 }
534
535 static void _caret_move_forward(void)
536 {
537         AtspiAccessible *current_widget = NULL;
538         AtspiText *text_interface;
539         gint current_offset;
540         gboolean ret;
541         int offset_pos;
542         gchar *text;
543         GError *err = NULL;
544         if (!current_obj)
545                 return;
546
547         current_widget = current_obj;
548
549         text_interface = atspi_accessible_get_text_iface(current_widget);
550         if (text_interface) {
551                 current_offset = atspi_text_get_caret_offset(text_interface, &err);
552                 GERROR_CHECK(err)
553                         ret = atspi_text_set_caret_offset(text_interface, current_offset + 1, &err);
554                 GERROR_CHECK(err)
555                         if (ret) {
556                         offset_pos = atspi_text_get_caret_offset(text_interface, NULL);
557                         text = atspi_text_get_text(text_interface, offset_pos, offset_pos + 1, NULL);
558                         DEBUG("Caret position increment done");
559                         DEBUG("Current caret position:%d", offset_pos);
560                         DEBUG("Current caret offset:%d", current_offset);
561                         if (offset_pos == atspi_text_get_character_count(text_interface, NULL)) {
562                                 DEBUG("SPEAK:%s", _("IDS_TEXT_END"));
563                                 tts_speak(_("IDS_TEXT_END"), EINA_FALSE);
564                         } else {
565                                 DEBUG("SPEAK:%s", text);
566                                 tts_speak(text, EINA_TRUE);
567                         }
568                         g_free(text);
569                 } else {
570                         ERROR("Caret position increment error");
571                 }
572                 g_object_unref(text_interface);
573         } else
574                 ERROR("No text interface supported!");
575         return;
576
577 }
578
579 static void _caret_move_backward(void)
580 {
581         AtspiAccessible *current_widget = NULL;
582         AtspiText *text_interface;
583         gint current_offset;
584         int offset_pos;
585         gchar *text;
586         GError *err = NULL;
587         gboolean ret;
588
589         if (!current_obj)
590                 return;
591
592         current_widget = current_obj;
593
594         GERROR_CHECK(err)
595
596                 text_interface = atspi_accessible_get_text_iface(current_widget);
597         if (text_interface) {
598                 current_offset = atspi_text_get_caret_offset(text_interface, &err);
599                 GERROR_CHECK(err)
600                         ret = atspi_text_set_caret_offset(text_interface, current_offset - 1, &err);
601                 GERROR_CHECK(err)
602                         if (ret) {
603                         offset_pos = atspi_text_get_caret_offset(text_interface, NULL);
604                         text = atspi_text_get_text(text_interface, offset_pos, offset_pos + 1, NULL);
605                         DEBUG("Caret position decrement done");
606                         DEBUG("Current caret position:%d", offset_pos);
607                         DEBUG("SPEAK:%s", text);
608                         tts_speak(text, EINA_TRUE);
609                         g_free(text);
610                         if (offset_pos == 0) {
611                                 DEBUG("SPEAK:%s", _("IDS_TEXT_BEGIN"));
612                                 tts_speak(_("IDS_TEXT_BEGIN"), EINA_FALSE);
613                         }
614                 } else {
615                         ERROR("Caret position decrement error");
616                 }
617                 g_object_unref(text_interface);
618         } else
619                 ERROR("No text interface supported!");
620         return;
621 }
622
623 static void _read_value(AtspiValue * value)
624 {
625         if (!value)
626                 return;
627
628         gdouble current_val = atspi_value_get_current_value(value, NULL);
629         gdouble max_val = atspi_value_get_maximum_value(value, NULL);
630         gdouble min_val = atspi_value_get_minimum_value(value, NULL);
631
632         int proc = (current_val / fabs(max_val - min_val)) * 100;
633
634         char buf[256] = "\0";
635         snprintf(buf, sizeof(buf), "%d percent", proc);
636         DEBUG("has value %s", buf);
637         tts_speak(buf, EINA_TRUE);
638 }
639
640 static void _value_inc(void)
641 {
642         AtspiAccessible *current_widget = NULL;
643         GError *err = NULL;
644
645         if (!current_obj)
646                 return;
647
648         current_widget = current_obj;
649
650         AtspiValue *value_interface = atspi_accessible_get_value_iface(current_widget);
651         if (value_interface) {
652                 DEBUG("Value interface supported!\n");
653                 gdouble current_val = atspi_value_get_current_value(value_interface, &err);
654                 GERROR_CHECK(err)
655                         DEBUG("Current value: %f\n ", (double)current_val);
656                 gdouble minimum_inc = atspi_value_get_minimum_increment(value_interface, &err);
657                 DEBUG("Minimum increment: %f\n ", (double)minimum_inc);
658                 GERROR_CHECK(err)
659                         atspi_value_set_current_value(value_interface, current_val + minimum_inc, &err);
660                 GERROR_CHECK(err)
661                         _read_value(value_interface);
662                 g_object_unref(value_interface);
663                 return;
664         }
665         ERROR("No value interface supported!\n");
666 }
667
668 static void _value_dec(void)
669 {
670         AtspiAccessible *current_widget = NULL;
671         GError *err = NULL;
672
673         if (!current_obj)
674                 return;
675         current_widget = current_obj;
676
677         AtspiValue *value_interface = atspi_accessible_get_value_iface(current_widget);
678         if (value_interface) {
679                 DEBUG("Value interface supported!\n");
680                 gdouble current_val = atspi_value_get_current_value(value_interface, &err);
681                 GERROR_CHECK(err)
682                         DEBUG("Current value: %f\n ", (double)current_val);
683                 gdouble minimum_inc = atspi_value_get_minimum_increment(value_interface, &err);
684                 GERROR_CHECK(err)
685                         DEBUG("Minimum increment: %f\n ", (double)minimum_inc);
686                 atspi_value_set_current_value(value_interface, current_val - minimum_inc, &err);
687                 GERROR_CHECK(err)
688                         _read_value(value_interface);
689                 g_object_unref(value_interface);
690                 return;
691         }
692         ERROR("No value interface supported!\n");
693 }
694
695 static void _activate_widget(void)
696 {
697         //activate the widget
698         //only if activate mean click
699         //special behavior for entry, caret should move from first/last last/first
700         DEBUG("START");
701         AtspiAccessible *current_widget = NULL;
702         AtspiComponent *focus_component = NULL;
703         AtspiAccessible *parent = NULL;
704         AtspiStateSet *ss = NULL;
705         AtspiSelection *selection = NULL;
706         AtspiAction *action;
707         AtspiEditableText *edit = NULL;
708
709         GError *err = NULL;
710         gchar *actionName = NULL;
711         gint number = 0;
712         gint i = 0;
713         gint index = 0;
714         Eina_Bool activate_found = EINA_FALSE;
715         AtspiRole role = ATSPI_ROLE_INVALID;
716
717         if (!current_obj)
718                 return;
719
720         if (!_widget_has_state(current_obj, ATSPI_STATE_ENABLED)) {
721                 DEBUG("Widget is disabled so cannot be activated");
722                 return;
723         }
724
725         current_widget = current_obj;
726
727         role = atspi_accessible_get_role(current_widget, NULL);
728         if (role == ATSPI_ROLE_SLIDER) {
729                 return;
730         }
731
732         display_info_about_object(current_widget, false);
733
734         edit = atspi_accessible_get_editable_text_iface(current_widget);
735         if (edit) {
736                 DEBUG("Activated object has editable Interface");
737                 focus_component = atspi_accessible_get_component_iface(current_widget);
738                 if (focus_component) {
739                         if (atspi_component_grab_focus(focus_component, &err) == TRUE) {
740                                 GERROR_CHECK(err)
741
742                                         DEBUG("Entry activated\n");
743
744                                 char *text_to_speak = NULL;
745                                 text_to_speak = generate_what_to_read(current_widget);
746
747                                 DEBUG("SPEAK:%s", text_to_speak);
748
749                                 tts_speak(text_to_speak, EINA_TRUE);
750                                 g_free(text_to_speak);
751                                 g_object_unref(focus_component);
752                         }
753                 }
754                 g_object_unref(edit);
755                 return;
756         }
757
758         action = atspi_accessible_get_action_iface(current_widget);
759         if (action) {
760                 number = atspi_action_get_n_actions(action, &err);
761                 DEBUG("Number of available action = %d\n", number);
762                 GERROR_CHECK(err)
763                         activate_found = EINA_FALSE;
764                 while (i < number && !activate_found) {
765                         actionName = atspi_action_get_name(action, i, &err);
766                         if (actionName && !strcmp("activate", actionName)) {
767                                 DEBUG("There is activate action");
768                                 activate_found = EINA_TRUE;
769                         } else {
770                                 i++;
771                         }
772                         g_free(actionName);
773                 }
774                 if (activate_found) {
775                         DEBUG("PERFORMING ATSPI ACTION NO.%d", i);
776                         atspi_action_do_action(action, i, &err);
777                 } else if (number > 0) {
778                         DEBUG("PERFORMING ATSPI DEFAULT ACTION");
779                         atspi_action_do_action(action, 0, &err);
780                 } else
781                         ERROR("There is no actions inside Action interface");
782                 if (action)
783                         g_object_unref(action);
784                 GERROR_CHECK(err)
785                         return;
786         }
787
788         ss = atspi_accessible_get_state_set(current_widget);
789         if (atspi_state_set_contains(ss, ATSPI_STATE_SELECTABLE) == EINA_TRUE) {
790                 DEBUG("OBJECT IS SELECTABLE");
791                 parent = atspi_accessible_get_parent(current_widget, NULL);
792                 if (parent) {
793                         index = atspi_accessible_get_index_in_parent(current_widget, NULL);
794                         selection = atspi_accessible_get_selection_iface(parent);
795                         if (selection) {
796                                 if(atspi_state_set_contains(ss, ATSPI_STATE_SELECTED)) {
797                                         atspi_selection_deselect_child (selection, index, NULL);
798
799                                 } else {
800                                         DEBUG("SELECT CHILD NO:%d\n", index);
801                                         atspi_selection_select_child(selection, index, NULL);
802                                 }
803
804                                 g_object_unref(selection);
805                                 g_object_unref(parent);
806                                 g_object_unref(ss);
807                                 return;
808                         } else
809                                 ERROR("no selection iterface in parent");
810
811                         g_object_unref(parent);
812                 }
813         }
814         g_object_unref(ss);
815
816 }
817
818 static void _quickpanel_change_state(gboolean quickpanel_switch)
819 {
820         DEBUG("START");
821 #ifdef X11_ENABLED
822         Ecore_X_Window xwin = 0;
823
824         if (quickpanel_switch)
825                 DEBUG("QUICKPANEL STATE ON");
826         else
827                 DEBUG("QUICKPANEL STATE OFF");
828
829         Ecore_X_Illume_Quickpanel_State state;
830
831         ecore_x_window_prop_xid_get(ecore_x_window_root_first_get(), ECORE_X_ATOM_NET_ACTIVE_WINDOW, ECORE_X_ATOM_WINDOW, &xwin, 1);
832
833         state = quickpanel_switch ? ECORE_X_ILLUME_QUICKPANEL_STATE_ON : ECORE_X_ILLUME_QUICKPANEL_STATE_OFF;
834
835         ecore_x_e_illume_quickpanel_state_set(xwin, state);
836
837         ecore_x_e_illume_quickpanel_state_send(ecore_x_e_illume_zone_get(xwin), state);
838
839         ecore_main_loop_iterate();
840 #endif
841 }
842
843 /**
844  * @brief Gets 'deepest' Scrollable accessible containing (x,y) point
845  */
846 /*
847 static AtspiScrollable*
848 _find_scrollable_ancestor_at_xy(int x, int y)
849 {
850    AtspiAccessible *ret = NULL;
851    AtspiRect *rect;
852    GError *err = NULL;
853
854    if (!top_window || !ATSPI_IS_COMPONENT(top_window))
855      {
856         DEBUG("No active window detected or no AtspiComponent interface available");
857         return NULL;
858      }
859
860    rect = atspi_component_get_extents(ATSPI_COMPONENT(top_window), ATSPI_COORD_TYPE_SCREEN, &err);
861    GERROR_CHECK(err)
862    if (!rect)
863      {
864         ERROR("Unable to fetch window screen coordinates");
865         return NULL;
866      }
867
868    // Scroll must originate within window borders
869    if ((x < rect->x) || (x > rect->x + rect->width) ||
870        (y < rect->y) || (y > rect->y + rect->height))
871      {
872         DEBUG("Scroll don't start within active window borders");
873         g_free(rect);
874         return NULL;
875      }
876
877    ret = atspi_component_get_accessible_at_point(ATSPI_COMPONENT(top_window), x, y, ATSPI_COORD_TYPE_SCREEN, &err);
878    GERROR_CHECK(err)
879    if (!ret)
880      {
881         ERROR("Unable to get accessible objct at (%d, %d) screen coordinates.", x, y);
882         return NULL;
883      }
884 gchar *name;
885 gchar *role;
886    // find accessible object with Scrollable interface
887    while (ret && (ret != top_window))
888      {
889        name = atspi_accessible_get_name(ret, &err);
890        GERROR_CHECK(err)
891        role = atspi_accessible_get_role_name(ret, &err);
892        GERROR_CHECK(err)
893        DEBUG("Testing for scrollability: %s %s",
894                    name, role);
895         if (atspi_accessible_get_scrollable(ret))
896           {
897              DEBUG("Scrollable widget found at (%d, %d), name: %s, role: %s", x, y,
898                    name ,role);
899              g_free(name);
900              g_free(role);
901              return ATSPI_SCROLLABLE(ret);
902           }
903         g_free(name);
904         g_free(role);
905         ret = atspi_accessible_get_parent(ret, &err);
906         if (err)
907           {
908              ERROR("Unable to fetch AT-SPI parent");
909              GERROR_CHECK(err)
910              return NULL;
911           }
912      }
913
914    return NULL;
915 }
916
917 static void _widget_scroll_begin(Gesture_Info *gi)
918 {
919    GError *err = NULL;
920
921    if (scrolled_obj)
922      {
923         ERROR("Scrolling context active when initializing new scrolling context! This should never happen.");
924         ERROR("Force reset of current scrolling context...");
925         atspi_scrollable_scroll_after_pointer(scrolled_obj, ATSPI_SCROLL_POINTER_END, gi->x_begin, gi->y_begin, &err);
926         if (err)
927           {
928              ERROR("Failed to reset scroll context.");
929              GERROR_CHECK(err)
930              scrolled_obj = NULL;
931           }
932      }
933
934    scrolled_obj = _find_scrollable_ancestor_at_xy(gi->x_begin, gi->y_begin);
935
936    if (!scrolled_obj)
937      {
938         DEBUG("No scrollable widget found at (%d, %d) coordinates", gi->x_begin, gi->y_begin);
939         return;
940      }
941
942    atspi_scrollable_scroll_after_pointer(scrolled_obj, ATSPI_SCROLL_POINTER_START, gi->x_begin, gi->y_begin, &err);
943    if (err)
944      {
945         ERROR("Failed to initialize scroll operation");
946         GERROR_CHECK(err)
947         scrolled_obj = NULL;
948      }
949 }
950
951 static void _widget_scroll_continue(Gesture_Info *gi)
952 {
953   GError *err = NULL;
954    if (!scrolled_obj)
955      {
956         DEBUG("Scrolling context not initialized!");
957         return;
958      }
959    atspi_scrollable_scroll_after_pointer(scrolled_obj, ATSPI_SCROLL_POINTER_CONTINUE, gi->x_begin, gi->y_begin, &err);
960    GERROR_CHECK(err)
961 }
962
963 static void _widget_scroll_end(Gesture_Info *gi)
964 {
965   GError *err = NULL;
966    if (!scrolled_obj)
967      {
968         ERROR("Scrolling context not initialized!");
969         return;
970      }
971
972    atspi_scrollable_scroll_after_pointer(scrolled_obj, ATSPI_SCROLL_POINTER_END, gi->x_begin, gi->y_begin, &err);
973    scrolled_obj = NULL;
974    GERROR_CHECK(err)
975 }
976 */
977
978 static void _widget_scroll(Gesture_Info * gi)
979 {
980         DEBUG("Recognized gesture state: %d", gi->state);
981
982         if (gi->state == 0) {
983                 DEBUG("save coordinates %d %d", gesture_start_p.x, gesture_start_p.y);
984                 gesture_start_p.x = gi->x_beg;
985                 gesture_start_p.y = gi->y_beg;
986         }
987
988         if (gi->state != 2) {
989                 DEBUG("Scroll not finished yet");
990                 return;
991         }
992
993         AtspiAccessible *obj = NULL;
994         obj = flat_navi_context_current_get(context);
995         if (!obj) {
996                 ERROR("No context");
997                 return;
998         }
999
1000         AtspiStateSet *ss = atspi_accessible_get_state_set(obj);
1001         if (!ss) {
1002                 ERROR("no stetes");
1003                 return;
1004         }
1005
1006         if (!atspi_state_set_contains(ss, ATSPI_STATE_SHOWING)) {
1007                 DEBUG("current context do not have visible state, swith to next/prev");
1008                 if (gesture_start_p.y > gi->y_end || gesture_start_p.x > gi->x_end) {
1009                         DEBUG("NEXT");
1010                         _focus_next_visible();
1011                 } else if (gesture_start_p.y < gi->y_end || gesture_start_p.x < gi->x_end) {
1012                         DEBUG("PREVIOUS");
1013                         _focus_prev_visible();
1014                 }
1015         }
1016         DEBUG("end");
1017         g_object_unref(ss);
1018         g_object_unref(obj);
1019 }
1020
1021 static void _read_quickpanel(void)
1022 {
1023         DEBUG("START");
1024
1025         device_time_get();
1026         device_battery_get();
1027         device_bluetooth_get();
1028         device_signal_strenght_get();
1029
1030         device_date_get();
1031         device_missed_events_get();
1032         DEBUG("END");
1033 }
1034
1035 static void _set_pause(void)
1036 {
1037         DEBUG("START");
1038
1039         Eina_Bool res = EINA_FALSE;
1040         bool pause = tts_pause_get();
1041         res = tts_pause_set(!pause);
1042         if (!res) {
1043                 ERROR("Failed to set pause state");
1044         }
1045
1046         DEBUG("END");
1047 }
1048
1049 void auto_review_highlight_set(void)
1050 {
1051         AtspiAccessible *obj = flat_navi_context_next(context);
1052
1053         DEBUG("START");
1054
1055         if (!obj) {
1056                 DEBUG("obj == NULL");
1057                 s_auto_review.auto_review_on = false;
1058                 return;
1059         } else if (obj == flat_navi_context_last_get(context)) {
1060                 DEBUG("obj == flat_navi_context_last_get()");
1061                 s_auto_review.auto_review_on = false;
1062         }
1063
1064         _current_highlight_object_set(obj);
1065
1066         DEBUG("END");
1067 }
1068
1069 void auto_review_highlight_top(void)
1070 {
1071         DEBUG("START");
1072         char *text_to_speak = NULL;
1073         AtspiAccessible *obj = flat_navi_context_current_get(context);
1074         AtspiAccessible *first = flat_navi_context_first(context);
1075
1076         if (first != obj) {
1077                 _current_highlight_object_set(first);
1078         } else {
1079                 text_to_speak = generate_what_to_read(obj);
1080                 DEBUG("Text to speak: %s", text_to_speak);
1081                 tts_speak(text_to_speak, EINA_TRUE);
1082                 free(text_to_speak);
1083         }
1084
1085         DEBUG("END");
1086 }
1087
1088 static void _on_auto_review_stop(void)
1089 {
1090         DEBUG("START");
1091         s_auto_review.auto_review_on = false;
1092         DEBUG("END");
1093 }
1094
1095 static void _on_utterance(void)
1096 {
1097         DEBUG("START");
1098         DEBUG("s_auto_review.auto_review_on == %d", s_auto_review.auto_review_on);
1099
1100         if (s_auto_review.auto_review_on) {
1101                 auto_review_highlight_set();
1102         }
1103         DEBUG("END");
1104 }
1105
1106 static void _review_from_current(void)
1107 {
1108         DEBUG("START");
1109
1110         s_auto_review.focused_object = flat_navi_context_current_get(context);
1111         s_auto_review.auto_review_on = true;
1112         auto_review_highlight_set();
1113
1114         DEBUG("END");
1115 }
1116
1117 static void _review_from_top()
1118 {
1119         DEBUG("START");
1120
1121         s_auto_review.focused_object = flat_navi_context_current_get(context);
1122         s_auto_review.auto_review_on = true;
1123         auto_review_highlight_top();
1124
1125         DEBUG("END");
1126 }
1127
1128 static void _direct_scroll_back(void)
1129 {
1130         DEBUG("ONE_FINGER_FLICK_LEFT_RETURN");
1131         if (!context) {
1132                 ERROR("No navigation context created");
1133                 return;
1134         }
1135
1136         AtspiAccessible *obj = NULL;
1137         AtspiAccessible *current = NULL;
1138         AtspiAccessible *parent = NULL;
1139         AtspiRole role;
1140
1141         current = flat_navi_context_current_get(context);
1142         parent = atspi_accessible_get_parent(current, NULL);
1143         role = atspi_accessible_get_role(parent, NULL);
1144
1145         if (role != ATSPI_ROLE_LIST) {
1146                 DEBUG("That operation can be done only on list, it is:%s", atspi_accessible_get_role_name(parent, NULL));
1147                 g_object_unref(parent);
1148                 g_object_unref(current);
1149                 return;
1150         }
1151
1152         int index = atspi_accessible_get_index_in_parent(current, NULL);
1153         int children_count = atspi_accessible_get_child_count(parent, NULL);
1154
1155         if (children_count <= 0) {
1156                 ERROR("NO visible element on list");
1157                 g_object_unref(parent);
1158                 g_object_unref(current);
1159                 return;
1160         }
1161
1162         DEBUG("start from element with index:%d/%d", index, children_count);
1163
1164         if (index <= 0) {
1165                 DEBUG("first element");
1166                 obj = atspi_accessible_get_child_at_index(parent, 0, NULL);
1167                 smart_notification(FOCUS_CHAIN_END_NOTIFICATION_EVENT, 0, 0);
1168         }
1169
1170         else {
1171                 DEBUG("go back to %d element", index);
1172                 obj = atspi_accessible_get_child_at_index(parent, index, NULL);
1173         }
1174
1175         if (obj) {
1176                 DEBUG("Will set highlight and context");
1177                 if (flat_navi_context_current_set(context, obj)) {
1178                         DEBUG("current obj set");
1179                 }
1180                 _current_highlight_object_set(obj);
1181         }
1182         g_object_unref(parent);
1183         g_object_unref(current);
1184 }
1185
1186 static void _direct_scroll_forward(void)
1187 {
1188         DEBUG("ONE_FINGER_FLICK_RIGHT_RETURN");
1189
1190         if (!context) {
1191                 ERROR("No navigation context created");
1192                 return;
1193         }
1194
1195         AtspiAccessible *obj = NULL;
1196         AtspiAccessible *current = NULL;
1197         AtspiAccessible *parent = NULL;
1198         AtspiRole role;
1199
1200         current = flat_navi_context_current_get(context);
1201         parent = atspi_accessible_get_parent(current, NULL);
1202         role = atspi_accessible_get_role(parent, NULL);
1203
1204         if (role != ATSPI_ROLE_LIST) {
1205                 DEBUG("That operation can be done only on list, it is:%s", atspi_accessible_get_role_name(parent, NULL));
1206                 g_object_unref(parent);
1207                 g_object_unref(current);
1208                 return;
1209         }
1210
1211         int index = atspi_accessible_get_index_in_parent(current, NULL);
1212         int children_count = atspi_accessible_get_child_count(parent, NULL);
1213
1214         if (children_count <= 0) {
1215                 ERROR("NO visible element on list");
1216                 g_object_unref(parent);
1217                 g_object_unref(current);
1218                 return;
1219         }
1220
1221         DEBUG("start from element with index:%d/%d", index, children_count);
1222
1223         if (index >= children_count) {
1224                 DEBUG("last element");
1225                 obj = atspi_accessible_get_child_at_index(parent, children_count - 1, NULL);
1226                 smart_notification(FOCUS_CHAIN_END_NOTIFICATION_EVENT, 0, 0);
1227         }
1228
1229         else {
1230                 DEBUG("go back to %d element", index);
1231                 obj = atspi_accessible_get_child_at_index(parent, index, NULL);
1232         }
1233
1234         if (obj) {
1235                 DEBUG("Will set highlight and context");
1236                 if (flat_navi_context_current_set(context, obj)) {
1237                         DEBUG("current obj set");
1238                 }
1239                 _current_highlight_object_set(obj);
1240         }
1241         g_object_unref(parent);
1242         g_object_unref(current);
1243 }
1244
1245 static void _direct_scroll_to_first(void)
1246 {
1247         DEBUG("ONE_FINGER_FLICK_UP_RETURN");
1248         if (!context) {
1249                 ERROR("No navigation context created");
1250                 return;
1251         }
1252         AtspiAccessible *obj = flat_navi_context_first(context);
1253         if (obj)
1254                 _current_highlight_object_set(obj);
1255         else
1256                 DEBUG("First widget not found. Abort");
1257         DEBUG("END");
1258 }
1259
1260 static void _direct_scroll_to_last(void)
1261 {
1262         DEBUG("ONE_FINGER_FLICK_DOWN_RETURN");
1263         if (!context) {
1264                 ERROR("No navigation context created");
1265                 return;
1266         }
1267         AtspiAccessible *obj = flat_navi_context_last(context);
1268         if (obj)
1269                 _current_highlight_object_set(obj);
1270         else
1271                 DEBUG("Last widget not found. Abort");
1272         DEBUG("END");
1273 }
1274
1275 static Eina_Bool _has_value(void)
1276 {
1277         DEBUG("START");
1278         AtspiAccessible *obj = NULL;
1279
1280         if (!current_obj)
1281                 return EINA_FALSE;
1282
1283         obj = current_obj;
1284
1285         if (!obj)
1286                 return EINA_FALSE;
1287
1288         AtspiValue *value = atspi_accessible_get_value_iface(obj);
1289
1290         if (value) {
1291                 g_object_unref(value);
1292                 return EINA_TRUE;
1293         }
1294
1295         return EINA_FALSE;
1296 }
1297
1298 static Eina_Bool _is_enabled(void)
1299 {
1300         if (!current_obj) {
1301                 return EINA_FALSE;
1302         }
1303
1304         return _widget_has_state(current_obj, ATSPI_STATE_ENABLED);
1305 }
1306
1307 static Eina_Bool _is_active_entry(void)
1308 {
1309         DEBUG("START");
1310
1311         if (!context) {
1312                 ERROR("No navigation context created");
1313                 return EINA_FALSE;
1314         }
1315         AtspiAccessible *obj = NULL;
1316         AtspiRole role;
1317         obj = flat_navi_context_current_get(context);
1318
1319         if (!obj)
1320                 return EINA_FALSE;
1321
1322         role = atspi_accessible_get_role(obj, NULL);
1323         if (role == ATSPI_ROLE_ENTRY) {
1324                 AtspiStateSet *state_set = atspi_accessible_get_state_set(obj);
1325                 if (atspi_state_set_contains(state_set, ATSPI_STATE_FOCUSED)) {
1326                         g_object_unref(state_set);
1327                         return EINA_TRUE;
1328                 }
1329                 g_object_unref(state_set);
1330                 return EINA_FALSE;
1331         }
1332
1333         DEBUG("END");
1334         return EINA_FALSE;
1335 }
1336
1337 static Eina_Bool _is_slider(AtspiAccessible * obj)
1338 {
1339         DEBUG("START");
1340
1341         if (!obj)
1342                 return EINA_FALSE;
1343
1344         AtspiRole role;
1345
1346         role = atspi_accessible_get_role(obj, NULL);
1347         if (role == ATSPI_ROLE_SLIDER) {
1348                 return EINA_TRUE;
1349         }
1350         return EINA_FALSE;
1351 }
1352
1353 static void _move_slider(Gesture_Info * gi)
1354 {
1355         DEBUG("ONE FINGER DOUBLE TAP AND HOLD");
1356
1357         if (!context) {
1358                 ERROR("No navigation context created");
1359                 return;
1360         }
1361
1362         AtspiAccessible *obj = NULL;
1363         AtspiValue *value = NULL;
1364         AtspiComponent *comp = NULL;
1365         AtspiRect *rect = NULL;
1366         int click_point_x = 0;
1367         int click_point_y = 0;
1368
1369         obj = current_obj;
1370
1371         if (!obj) {
1372                 DEBUG("no object");
1373                 prepared = false;
1374                 return;
1375         }
1376
1377         if (!_is_slider(obj)) {
1378                 DEBUG("Object is not a slider");
1379                 prepared = false;
1380                 return;
1381         }
1382
1383         if (!_widget_has_state(obj, ATSPI_STATE_ENABLED)) {
1384                 DEBUG("Slider is disabled");
1385                 prepared = false;
1386                 return;
1387         }
1388
1389         if (gi->state == 0) {
1390                 comp = atspi_accessible_get_component_iface(obj);
1391                 if (!comp) {
1392                         ERROR("that slider do not have component interface");
1393                         prepared = false;
1394                         return;
1395                 }
1396
1397                 rect = atspi_component_get_extents(comp, ATSPI_COORD_TYPE_SCREEN, NULL);
1398
1399                 DEBUG("Current object is in:%d %d", rect->x, rect->y);
1400                 DEBUG("Current object has size:%d %d", rect->width, rect->height);
1401
1402                 click_point_x = rect->x + rect->width / 2;
1403                 click_point_y = rect->y + rect->height / 2;
1404                 DEBUG("Click on point %d %d", click_point_x, click_point_y);
1405                 start_scroll(click_point_x, click_point_y);
1406         }
1407
1408         if (gi->state == 1) {
1409                 counter++;
1410                 DEBUG("SCROLLING but not meet counter:%d", counter);
1411                         if (counter >= GESTURE_LIMIT) {
1412                         counter = 0;
1413                         DEBUG("Scroll on point %d %d", gi->x_end, gi->y_end);
1414                         continue_scroll(gi->x_end, gi->y_end);
1415                 }
1416         }
1417
1418         if (gi->state == 2) {
1419                 DEBUG("state == 2");
1420                 end_scroll(gi->x_end, gi->y_end);
1421                 prepared = false;
1422                 value = atspi_accessible_get_value_iface(obj);
1423                 if (value) {
1424                         _read_value(value);
1425                         g_object_unref(value);
1426                 } else {
1427                         ERROR("There is not value interface in slider");
1428                 }
1429         }
1430         DEBUG("END");
1431 }
1432
1433 AtspiAction *_get_main_window(void)
1434 {
1435         AtspiAccessible *win = flat_navi_context_root_get(context);
1436         if (!win) {
1437                 ERROR("win == NULL");
1438                 return NULL;
1439         }
1440
1441         AtspiAction *action = atspi_accessible_get_action_iface(win);
1442         if (!action) {
1443                 ERROR("action == NULL");
1444                 return NULL;
1445         }
1446
1447         return action;
1448 }
1449
1450 static int _find_action_index(AtspiAction * action, char *action_name_to_find)
1451 {
1452         int action_num = atspi_action_get_n_actions(action, NULL);
1453         char *action_name = NULL;
1454
1455         int i = 0;
1456         for (i = 0; i < action_num; ++i) {
1457                 action_name = atspi_action_get_action_name(action, i, NULL);
1458
1459                 if (!strcmp(action_name_to_find, action_name)) {
1460                         return i;
1461                 }
1462         }
1463
1464         return -i;
1465 }
1466
1467 static void _start_stop_signal_send(void)
1468 {
1469         int action_index = -1;
1470         char *action_name = "pause_play";
1471         AtspiAction *action = _get_main_window();
1472         if (!action) {
1473                 ERROR("Could not get the action inteface");
1474         }
1475
1476         if (!action) {
1477                 ERROR("action == NULL");
1478                 return;
1479         }
1480
1481         action_index = _find_action_index(action, action_name);
1482         if (action_index < 0) {
1483                 ERROR("Pause_play action not found");
1484                 return;
1485         }
1486
1487         DEBUG("ACTION: %s has index: %d", action_name, action_index);
1488         atspi_action_do_action(action, action_index, NULL);
1489 }
1490
1491 static void on_gesture_detected(void *data, Gesture_Info * info)
1492 {
1493 #ifdef X11_ENABLED
1494         Ecore_X_Window keyboard_win;
1495 #endif
1496         _on_auto_review_stop();
1497
1498         if (info->type == ONE_FINGER_SINGLE_TAP && info->state == 3) {
1499                 DEBUG("One finger single tap aborted");
1500                 prepared = true;
1501         }
1502
1503         switch (info->type) {
1504         case ONE_FINGER_HOVER:
1505                 if (prepared) {
1506                         DEBUG("Prepare to move slider");
1507                         _move_slider(info);
1508                 } else {
1509                         if (_last_hover_event_time < 0)
1510                                 _last_hover_event_time = info->event_time;
1511                         //info->event_time and _last_hover_event_time contain timestamp in ms.
1512                         //RETURN so we do not handle all incoming event
1513                         if ((info->event_time - _last_hover_event_time) < ONGOING_HOVER_GESTURE_INTERPRETATION_INTERVAL && info->state == 1)
1514                                 return;
1515                         _last_hover_event_time = info->state != 1 ? -1 : info->event_time;
1516 #if defined(ELM_ACCESS_KEYBOARD) && defined(X11_ENABLED)
1517                         keyboard_win = top_window_get(info->x_end, info->y_end);
1518                         if (keyboard_win && ecore_x_e_virtual_keyboard_get(keyboard_win)) {
1519                                 elm_access_adaptor_emit_read(keyboard_win, info->x_end, info->y_end);
1520                                 break;
1521                         }
1522 #endif
1523                         _focus_widget(info);
1524                 }
1525                 break;
1526         case TWO_FINGERS_HOVER:
1527                 _widget_scroll(info);
1528                 break;
1529         case ONE_FINGER_FLICK_LEFT:
1530                 _focus_prev();
1531                 break;
1532         case ONE_FINGER_FLICK_RIGHT:
1533                 _focus_next();
1534                 break;
1535         case ONE_FINGER_FLICK_UP:
1536                 if (_is_active_entry())
1537                         _caret_move_backward();
1538                 else if (_has_value() && _is_enabled())
1539                         _value_inc();
1540                 else
1541                         _focus_prev();
1542                 break;
1543         case ONE_FINGER_FLICK_DOWN:
1544                 if (_is_active_entry())
1545                         _caret_move_forward();
1546                 else if (_has_value() && _is_enabled())
1547                         _value_dec();
1548                 else
1549                         _focus_next();
1550                 break;
1551         case ONE_FINGER_SINGLE_TAP:
1552 #if defined(ELM_ACCESS_KEYBOARD) && defined(X11_ENABLED)
1553                 keyboard_win = top_window_get(info->x_end, info->y_end);
1554                 if (keyboard_win && ecore_x_e_virtual_keyboard_get(keyboard_win)) {
1555                         elm_access_adaptor_emit_read(keyboard_win, info->x_end, info->y_end);
1556                         break;
1557                 }
1558 #endif
1559                 if (!prepared)
1560                         _focus_widget(info);
1561                 break;
1562         case ONE_FINGER_DOUBLE_TAP:
1563 #if defined(ELM_ACCESS_KEYBOARD) && defined(X11_ENABLED)
1564                 keyboard_win = top_window_get(info->x_end, info->y_end);
1565                 if (keyboard_win && ecore_x_e_virtual_keyboard_get(keyboard_win)) {
1566                         elm_access_adaptor_emit_activate(keyboard_win, info->x_end, info->y_end);
1567                         break;
1568                 }
1569 #endif
1570                 _activate_widget();
1571                 break;
1572         case TWO_FINGERS_SINGLE_TAP:
1573                 _set_pause();
1574                 break;
1575         case TWO_FINGERS_DOUBLE_TAP:
1576                 _start_stop_signal_send();
1577                 break;
1578         case TWO_FINGERS_TRIPLE_TAP:
1579 #ifndef SCREEN_READER_TV
1580                 _read_quickpanel();
1581 #endif
1582                 break;
1583         case THREE_FINGERS_SINGLE_TAP:
1584                 _review_from_top();
1585                 break;
1586         case THREE_FINGERS_DOUBLE_TAP:
1587                 _review_from_current();
1588                 break;
1589         case THREE_FINGERS_FLICK_DOWN:
1590                 _quickpanel_change_state(QUICKPANEL_DOWN);
1591                 break;
1592         case THREE_FINGERS_FLICK_UP:
1593                 _quickpanel_change_state(QUICKPANEL_UP);
1594                 break;
1595         case ONE_FINGER_FLICK_LEFT_RETURN:
1596                 _direct_scroll_back();
1597                 break;
1598         case ONE_FINGER_FLICK_RIGHT_RETURN:
1599                 _direct_scroll_forward();
1600                 break;
1601         case ONE_FINGER_FLICK_UP_RETURN:
1602                 if (_is_active_entry())
1603                         _caret_move_beg();
1604                 else
1605                         _direct_scroll_to_first();
1606                 break;
1607         case ONE_FINGER_FLICK_DOWN_RETURN:
1608                 if (_is_active_entry())
1609                         _caret_move_end();
1610                 else
1611                         _direct_scroll_to_last();
1612                 break;
1613         default:
1614                 DEBUG("Gesture type %d not handled in switch", info->type);
1615         }
1616
1617         dbus_gesture_adapter_emit(info);
1618 }
1619
1620 static void _view_content_changed(AtspiAccessible * root, void *user_data)
1621 {
1622         if (flat_navi_is_valid(context, root))
1623                 return;
1624         if (!_widget_has_state(root, ATSPI_STATE_SHOWING))
1625                 return;
1626         flat_navi_context_free(context);
1627         context = flat_navi_context_create(root);
1628         _current_highlight_object_set(flat_navi_context_current_get(context));
1629 }
1630
1631 static void _new_highlighted_obj_changed(AtspiAccessible * new_highlighted_obj, void *user_data)
1632 {
1633         DEBUG("context: %p, current: %p, new_highlighted_obj: %p", context, flat_navi_context_current_get(context), new_highlighted_obj);
1634         if (context && flat_navi_context_current_get(context) != new_highlighted_obj) {
1635                 flat_navi_context_current_set(context, g_object_ref(new_highlighted_obj));
1636         }
1637 }
1638
1639 void clear(gpointer d)
1640 {
1641         AtspiAccessible **data = d;
1642         AtspiAccessible *obj = *data;
1643         g_object_unref(obj);
1644 }
1645
1646 static AtspiAccessible *_get_modal_descendant(AtspiAccessible * root)
1647 {
1648         GError *err = NULL;
1649         AtspiStateSet *states = atspi_state_set_new(NULL);
1650         atspi_state_set_add(states, ATSPI_STATE_MODAL);
1651         atspi_state_set_add(states, ATSPI_STATE_SHOWING);
1652         atspi_state_set_add(states, ATSPI_STATE_VISIBLE);
1653         DEBUG("GET MODAL: STATE SET PREPARED");
1654         AtspiMatchRule *rule = atspi_match_rule_new(states,
1655                                                                                                 ATSPI_Collection_MATCH_ALL,
1656                                                                                                 NULL,
1657                                                                                                 ATSPI_Collection_MATCH_INVALID,
1658                                                                                                 NULL,
1659                                                                                                 ATSPI_Collection_MATCH_INVALID,
1660                                                                                                 NULL,
1661                                                                                                 ATSPI_Collection_MATCH_INVALID,
1662                                                                                                 FALSE);
1663         DEBUG("GET MODAL: MATCHING RULE PREPARED");
1664         AtspiAccessible *ret = NULL;
1665         AtspiCollection *col_iface = atspi_accessible_get_collection_iface(root);
1666         GArray *result = atspi_collection_get_matches(col_iface,
1667                                                                                                   rule,
1668                                                                                                   ATSPI_Collection_SORT_ORDER_CANONICAL,
1669                                                                                                   1,
1670                                                                                                   TRUE,
1671                                                                                                   &err);
1672         GERROR_CHECK(err);
1673         DEBUG("GET MODAL: QUERY PERFORMED");
1674         g_object_unref(states);
1675         g_object_unref(rule);
1676         g_object_unref(col_iface);
1677         if (result && result->len > 0) {
1678                 DEBUG("GET MODAL: MODAL FOUND");
1679                 g_array_set_clear_func(result, clear);
1680                 ret = g_object_ref(g_array_index(result, AtspiAccessible *, 0));
1681                 g_array_free(result, TRUE);
1682         }
1683         return ret;
1684 }
1685
1686 static void on_window_activate(void *data, AtspiAccessible * window)
1687 {
1688         DEBUG("START");
1689
1690         if (top_window)
1691                 app_tracker_callback_unregister(top_window, _view_content_changed, NULL);
1692
1693         if (window) {
1694                 DEBUG("Window name: %s", atspi_accessible_get_name(window, NULL));
1695                 // TODO: modal descendant of window should be used (if exists) otherwise window
1696                 AtspiAccessible *modal_descendant = _get_modal_descendant(window);
1697                 app_tracker_callback_register(modal_descendant ? modal_descendant : window, _view_content_changed, NULL);
1698                 _view_content_changed(modal_descendant ? modal_descendant : window, NULL);
1699                 g_object_unref(modal_descendant);
1700         } else {
1701                 flat_navi_context_free(context);
1702                 ERROR("No top window found!");
1703         }
1704         top_window = window;
1705         DEBUG("END");
1706 }
1707
1708 void kb_tracker(void *data, Key k)
1709 {
1710         switch (k) {
1711         case KEY_LEFT:
1712                 _focus_prev();
1713                 break;
1714         case KEY_RIGHT:
1715                 _focus_next();
1716                 break;
1717         default:
1718                 DEBUG("Key %d not supported \n", k);
1719         }
1720 }
1721
1722 void navigator_init(void)
1723 {
1724         DEBUG("START");
1725
1726         set_utterance_cb(_on_utterance);
1727
1728         screen_reader_gestures_tracker_register(on_gesture_detected, NULL);
1729         //FIXME add some config to get script path
1730         if (lua_engine_init(SCRIPTDIR "/mobile.lua"))
1731                 ERROR("Failed to init lua engine.");
1732         dbus_gesture_adapter_init();
1733         app_tracker_init();
1734         app_tracker_new_obj_highlighted_callback_register(_new_highlighted_obj_changed);
1735         window_tracker_init();
1736         window_tracker_register(on_window_activate, NULL);
1737         window_tracker_active_window_request();
1738         smart_notification_init();
1739 #ifndef SCREEN_READER_TV
1740         system_notifications_init();
1741 #endif
1742         keyboard_tracker_init();
1743         keyboard_tracker_register(kb_tracker, NULL);
1744 }
1745
1746 void navigator_shutdown(void)
1747 {
1748         GError *err = NULL;
1749         if (current_obj) {
1750                 AtspiComponent *comp = atspi_accessible_get_component_iface(current_obj);
1751                 if (comp) {
1752                         atspi_component_clear_highlight(comp, &err);
1753                         GERROR_CHECK(err);
1754                 }
1755         }
1756         if (context) {
1757                 flat_navi_context_free(context);
1758                 context = NULL;
1759         }
1760         lua_engine_shutdown();
1761         dbus_gesture_adapter_shutdown();
1762         app_tracker_shutdown();
1763         window_tracker_shutdown();
1764         smart_notification_shutdown();
1765 #ifndef SCREEN_READER_TV
1766         system_notifications_shutdown();
1767 #endif
1768         keyboard_tracker_shutdown();
1769 }