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