2 * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
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
8 * http://floralicense.org/license/
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.
20 #include <atspi/atspi.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"
35 #define QUICKPANEL_DOWN TRUE
36 #define QUICKPANEL_UP FALSE
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
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
54 #define GERROR_CHECK(error)\
57 ERROR("Error_log:%s",error->message);\
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;
75 int _last_hover_event_time = -1;
79 AtspiAccessible *focused_object;
83 .focused_object = NULL,
84 .auto_review_on = false
88 state_to_char(AtspiStateType state)
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");
189 display_info_about_object(AtspiAccessible *obj)
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);
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));
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));
219 for (a = 0; states && (a < states->len); ++a)
221 stat = g_array_index (states, AtspiStateType, a);
222 state_name = state_to_char(stat);
223 DEBUG(" %s", state_name);
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("------------------------");
237 generate_description_for_subtrees(AtspiAccessible *obj)
250 char ret[TTS_MAX_TEXT_SIZE] = "\0";
251 AtspiAccessible *child = NULL;
253 int child_count = atspi_accessible_get_child_count(obj, NULL);
255 role = atspi_accessible_get_role(obj, NULL);
257 // Do not generate that for popups
258 if (role == ATSPI_ROLE_POPUP_MENU || role == ATSPI_ROLE_DIALOG)
261 child_count = atspi_accessible_get_child_count(obj, NULL);
263 DEBUG("There is %d children inside this object", child_count);
267 for (i=0; i < child_count; i++)
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))
274 strncat(ret, name, sizeof(ret) - strlen(ret) - 1);
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))
281 strncat(ret, below, sizeof(ret) - strlen(ret) - 1);
284 g_object_unref(child);
293 _check_list_children_count(AtspiAccessible *obj)
297 AtspiAccessible *child = NULL;
302 if (atspi_accessible_get_role(obj, NULL) == ATSPI_ROLE_LIST)
304 int children_count = atspi_accessible_get_child_count(obj, NULL);
306 for (i=0; i<children_count; i++)
308 child = atspi_accessible_get_child_at_index(obj, i, NULL);
309 if (atspi_accessible_get_role(child, NULL) == ATSPI_ROLE_LIST_ITEM)
311 g_object_unref(child);
319 _find_popup_list_children_count(AtspiAccessible *obj)
321 int list_items_count = 0;
322 int children_count = atspi_accessible_get_child_count(obj, NULL);
324 AtspiAccessible *child = NULL;
326 list_items_count = _check_list_children_count(obj);
327 if (list_items_count > 0)
328 return list_items_count;
330 for (i=0; i<children_count; i++)
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);
343 generate_trait(AtspiAccessible *obj)
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)
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);
359 strncat(ret, _("IDS_TRAIT_TEXT_EDIT"), sizeof(ret) - strlen(ret) - 1);
362 else if (role == ATSPI_ROLE_MENU_ITEM)
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);
371 else if (role == ATSPI_ROLE_POPUP_MENU)
373 int children_count = atspi_accessible_get_child_count(obj, NULL);
374 char trait[HOVERSEL_TRAIT_SIZE];
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);
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);
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);
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);
392 snprintf(trait, HOVERSEL_TRAIT_SIZE, _("IDS_TRAIT_POPUP_CLOSE"));
393 strncat(ret, trait, sizeof(ret) - strlen(ret) - 1);
395 else if (role == ATSPI_ROLE_DIALOG)
397 int children_count = _find_popup_list_children_count(obj);
398 char trait[HOVERSEL_TRAIT_SIZE];
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);
404 if(children_count > 0)
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);
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);
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);
419 snprintf(trait, HOVERSEL_TRAIT_SIZE, _("IDS_TRAIT_POPUP_CLOSE"));
420 strncat(ret, trait, sizeof(ret) - strlen(ret) - 1);
422 else if (role == ATSPI_ROLE_GLASS_PANE)
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);
430 else if (role == ATSPI_ROLE_LIST_ITEM && atspi_state_set_contains(state_set, ATSPI_STATE_EXPANDABLE))
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);
437 strncat(ret, _("IDS_TRAIT_GROUP_INDEX_COLLAPSED"), sizeof(ret) - strlen(ret) - 1);
441 char *role_name = atspi_accessible_get_localized_role_name(obj, NULL);
442 strncat(ret, role_name, sizeof(ret) - strlen(ret) - 1);
446 if (state_set) g_object_unref(state_set);
452 generate_what_to_read(AtspiAccessible *obj)
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);
468 text = atspi_text_get_text(iface_text,
470 atspi_text_get_character_count(iface_text, NULL),
472 g_object_unref(iface_text);
475 DEBUG("->->->->->-> WIDGET GAINED HIGHLIGHT: %s <-<-<-<-<-<-<-", name);
476 DEBUG("->->->->->-> FROM SUBTREE HAS NAME: %s <-<-<-<-<-<-<-", other);
478 display_info_about_object(obj);
480 if (name && strncmp(name, "\0", 1))
481 names = strdup(name);
482 else if (other && strncmp(other, "\0", 1))
483 names = strdup(other);
487 strncat(ret, text, sizeof(ret) - strlen(ret) - 1);
488 strncat(ret, ", ", sizeof(ret) - strlen(ret) - 1);
491 DEBUG("Text:%s", text);
495 strncat(ret, names, sizeof(ret) - strlen(ret) - 1);
496 strncat(ret, ", ", sizeof(ret) - strlen(ret) - 1);
500 strncat(ret, role_name, sizeof(ret) - strlen(ret) - 1);
504 if (strncmp(description, "\0", 1))
505 strncat(ret, ", ", sizeof(ret) - strlen(ret) - 1);
506 strncat(ret, description, sizeof(ret) - strlen(ret) - 1);
521 _current_highlight_object_set(AtspiAccessible *obj)
529 DEBUG("Clearing highlight object");
533 atspi_component_clear_highlight(current_comp, &err);
534 g_object_ref(current_comp);
540 if (current_obj == obj)
542 DEBUG("Object already highlighted");
543 DEBUG("Object name:%s", atspi_accessible_get_name(obj, NULL));
546 if (obj && ATSPI_IS_COMPONENT(obj))
548 DEBUG("OBJ WITH COMPONENT");
549 AtspiComponent *comp = atspi_accessible_get_component_iface(obj);
553 role = atspi_accessible_get_role_name(obj, &err);
554 ERROR("AtspiComponent *comp NULL, [%s]", role);
561 atspi_component_clear_highlight(current_comp, &err);
563 atspi_component_grab_highlight(comp, &err);
567 Eina_Bool is_paused = tts_pause_get();
571 tts_pause_set(EINA_FALSE);
574 char *text_to_speak = NULL;
575 text_to_speak = generate_what_to_read(obj);
576 DEBUG("SPEAK:%s", text_to_speak);
578 tts_speak(text_to_speak, EINA_TRUE);
579 g_free(text_to_speak);
582 DEBUG("Unable to highlight on object");
586 void test_debug(AtspiAccessible *current_widget)
592 AtspiAccessible *child_iter = NULL;
593 AtspiAccessible *parent = atspi_accessible_get_parent(current_widget, &err);
598 count_child = atspi_accessible_get_child_count(parent, &err);
600 DEBUG("Total childs in parent: %d\n", count_child);
604 for(jdx = 0; jdx < count_child; jdx++)
606 child_iter = atspi_accessible_get_child_at_index(parent, jdx, &err);
609 if(current_widget == child_iter)
611 role = atspi_accessible_get_role_name(parent, &err);
612 DEBUG("Childen found in parent: %s at index: %d\n", role, jdx);
616 role = atspi_accessible_get_role_name(parent, &err);
617 DEBUG("Childen not found in parent: %s at index: %d\n", role, jdx);
624 static void _focus_widget(Gesture_Info *info)
627 if (info->type == ONE_FINGER_HOVER)
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)
635 _last_hover_event_time = info->state != 1 ? -1 : info->event_time;
638 if ((last_focus.x == info->x_beg) && (last_focus.y == info->y_beg))
641 AtspiAccessible *obj = NULL;
642 if (flat_navi_context_current_at_x_y_set(context, info->x_beg, info->y_beg, &obj))
644 last_focus.x = info->x_beg;
645 last_focus.y = info->y_beg;
646 _current_highlight_object_set(obj);
652 static void _focus_next(void)
655 AtspiAccessible *obj;
658 ERROR("No navigation context created");
662 obj = flat_navi_context_next(context);
664 _current_highlight_object_set(obj);
666 DEBUG("Next widget not found. Abort");
670 static void _focus_next_visible(void)
673 AtspiAccessible *obj;
674 AtspiStateSet *ss = NULL;
675 Eina_Bool visible = EINA_FALSE;
678 ERROR("No navigation context created");
684 obj = flat_navi_context_next(context);
685 // try 'cycle' objects in context
688 ss = atspi_accessible_get_state_set(obj);
689 visible = atspi_state_set_contains(ss, ATSPI_STATE_SHOWING);
693 while (obj && !visible);
696 _current_highlight_object_set(obj);
698 DEBUG("Next widget not found. Abort");
702 static void _focus_prev_visible(void)
704 AtspiAccessible *obj;
705 AtspiStateSet *ss = NULL;
706 Eina_Bool visible = EINA_FALSE;
709 ERROR("No navigation context created");
714 obj = flat_navi_context_prev(context);
715 // try 'cycle' objects in context
718 ss = atspi_accessible_get_state_set(obj);
719 visible = atspi_state_set_contains(ss, ATSPI_STATE_SHOWING);
723 while (obj && !visible);
726 _current_highlight_object_set(obj);
728 DEBUG("Previous widget not found. Abort");
731 static void _focus_prev(void)
733 AtspiAccessible *obj;
736 ERROR("No navigation context created");
740 obj = flat_navi_context_prev(context);
742 _current_highlight_object_set(obj);
744 DEBUG("Previous widget not found. Abort");
747 static void _caret_move_beg(void)
749 AtspiAccessible* current_widget = NULL;
750 AtspiText *text_interface;
757 current_widget = current_obj;
759 text_interface = atspi_accessible_get_text_iface(current_widget);
762 ret = atspi_text_set_caret_offset(text_interface, 0, &err);
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);
775 ERROR("Caret position increment error");
777 g_object_unref(text_interface);
780 ERROR("No text interface supported!");
783 static void _caret_move_end(void)
785 AtspiAccessible* current_widget = NULL;
786 AtspiText *text_interface;
793 current_widget = current_obj;
795 text_interface = atspi_accessible_get_text_iface(current_widget);
798 int len = atspi_text_get_character_count (text_interface, NULL);
799 ret = atspi_text_set_caret_offset(text_interface, len, &err);
802 DEBUG("Caret position increment done");
803 DEBUG("SPEAK:%s", _("IDS_TEXT_END"));
804 tts_speak(_("IDS_TEXT_END"), EINA_TRUE);
807 ERROR("Caret position to end error");
808 g_object_unref(text_interface);
812 static void _caret_move_forward(void)
814 AtspiAccessible* current_widget = NULL;
815 AtspiText *text_interface;
824 current_widget = current_obj;
826 text_interface = atspi_accessible_get_text_iface(current_widget);
829 current_offset = atspi_text_get_caret_offset(text_interface, &err);
831 ret = atspi_text_set_caret_offset(text_interface, current_offset + 1, &err);
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))
842 DEBUG("SPEAK:%s", _("IDS_TEXT_END"));
843 tts_speak(_("IDS_TEXT_END"), EINA_FALSE);
847 DEBUG("SPEAK:%s", text);
848 tts_speak(text, EINA_TRUE);
854 ERROR("Caret position increment error");
856 g_object_unref(text_interface);
859 ERROR("No text interface supported!");
864 static void _caret_move_backward(void)
866 AtspiAccessible* current_widget = NULL;
867 AtspiText *text_interface;
877 current_widget = current_obj;
881 text_interface = atspi_accessible_get_text_iface(current_widget);
884 current_offset = atspi_text_get_caret_offset(text_interface, &err);
886 ret = atspi_text_set_caret_offset(text_interface, current_offset - 1, &err);
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);
899 DEBUG("SPEAK:%s", _("IDS_TEXT_BEGIN"));
900 tts_speak(_("IDS_TEXT_BEGIN"), EINA_FALSE);
905 ERROR("Caret position decrement error");
907 g_object_unref(text_interface);
910 ERROR("No text interface supported!");
914 static void _read_value( AtspiValue *value)
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);
923 int proc = (current_val/fabs(max_val-min_val)) * 100;
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);
931 static void _value_inc(void)
933 AtspiAccessible* current_widget = NULL;
939 current_widget = current_obj;
941 AtspiValue *value_interface = atspi_accessible_get_value_iface(current_widget);
944 DEBUG("Value interface supported!\n");
945 gdouble current_val = atspi_value_get_current_value(value_interface, &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);
951 atspi_value_set_current_value(value_interface, current_val + minimum_inc, &err);
953 _read_value(value_interface);
954 g_object_unref(value_interface);
957 ERROR("No value interface supported!\n");
960 static void _value_dec(void)
962 AtspiAccessible* current_widget = NULL;
967 current_widget = current_obj;
969 AtspiValue *value_interface = atspi_accessible_get_value_iface(current_widget);
972 DEBUG("Value interface supported!\n");
973 gdouble current_val = atspi_value_get_current_value(value_interface, &err);
975 DEBUG("Current value: %f\n ", (double)current_val);
976 gdouble minimum_inc = atspi_value_get_minimum_increment(value_interface, &err);
978 DEBUG("Minimum increment: %f\n ", (double)minimum_inc);
979 atspi_value_set_current_value(value_interface, current_val - minimum_inc, &err);
981 _read_value(value_interface);
982 g_object_unref(value_interface);
985 ERROR("No value interface supported!\n");
989 _check_if_widget_is_enabled(AtspiAccessible *obj)
991 Eina_Bool ret = EINA_FALSE;
992 AtspiStateSet *st = atspi_accessible_get_state_set (obj);
994 if (atspi_state_set_contains(st, ATSPI_STATE_ENABLED))
1001 static void _activate_widget(void)
1003 //activate the widget
1004 //only if activate mean click
1005 //special behavior for entry, caret should move from first/last last/first
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;
1016 gchar *actionName = NULL;
1020 Eina_Bool activate_found = EINA_FALSE;
1021 AtspiRole role = ATSPI_ROLE_INVALID;
1026 if (!_check_if_widget_is_enabled(current_obj))
1028 DEBUG("Widget disable so cannot be activated");
1032 current_widget = current_obj;
1034 role = atspi_accessible_get_role (current_widget, NULL);
1035 if(role == ATSPI_ROLE_SLIDER)
1040 display_info_about_object(current_widget);
1042 edit = atspi_accessible_get_editable_text_iface (current_widget);
1045 DEBUG("Activated object has editable Interface");
1046 focus_component = atspi_accessible_get_component_iface(current_widget);
1047 if (focus_component)
1049 if (atspi_component_grab_focus(focus_component, &err) == TRUE)
1053 DEBUG("Entry activated\n");
1055 char *text_to_speak = NULL;
1056 text_to_speak = generate_what_to_read(current_widget);
1058 DEBUG("SPEAK:%s", text_to_speak);
1060 tts_speak(text_to_speak, EINA_TRUE);
1061 g_free(text_to_speak);
1062 g_object_unref(focus_component);
1065 g_object_unref(edit);
1069 action = atspi_accessible_get_action_iface(current_widget);
1072 number = atspi_action_get_n_actions(action, &err);
1073 DEBUG("Number of available action = %d\n", number);
1075 activate_found = EINA_FALSE;
1076 while (i < number && !activate_found)
1078 actionName = atspi_action_get_name(action, i, &err);
1079 if (actionName && !strcmp("activate", actionName))
1081 DEBUG("There is activate action");
1082 activate_found = EINA_TRUE;
1092 DEBUG("PERFORMING ATSPI ACTION NO.%d", i);
1093 atspi_action_do_action(action, i, &err);
1095 else if (number > 0)
1097 DEBUG("PERFORMING ATSPI DEFAULT ACTION");
1098 atspi_action_do_action(action, 0, &err);
1101 ERROR("There is no actions inside Action interface");
1102 if (action) g_object_unref(action);
1107 ss = atspi_accessible_get_state_set(current_widget);
1108 if (atspi_state_set_contains(ss, ATSPI_STATE_SELECTABLE) == EINA_TRUE)
1110 DEBUG("OBJECT IS SELECTABLE");
1111 parent = atspi_accessible_get_parent(current_widget, NULL);
1114 index = atspi_accessible_get_index_in_parent(current_widget, NULL);
1115 selection = atspi_accessible_get_selection_iface (parent);
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);
1126 ERROR("no selection iterface in parent");
1133 static void _quickpanel_change_state(gboolean quickpanel_switch)
1136 Ecore_X_Window xwin = 0;
1138 ERROR(quickpanel_switch ? "QUICKPANEL STATE ON" : "QUICKPANEL STATE OFF");
1140 Ecore_X_Illume_Quickpanel_State state;
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,
1149 state = quickpanel_switch ? ECORE_X_ILLUME_QUICKPANEL_STATE_ON : ECORE_X_ILLUME_QUICKPANEL_STATE_OFF;
1151 ecore_x_e_illume_quickpanel_state_set(xwin, state);
1153 ecore_x_e_illume_quickpanel_state_send(ecore_x_e_illume_zone_get(xwin), state);
1155 ecore_main_loop_iterate();
1159 * @brief Gets 'deepest' Scrollable accessible containing (x,y) point
1162 static AtspiScrollable*
1163 _find_scrollable_ancestor_at_xy(int x, int y)
1165 AtspiAccessible *ret = NULL;
1169 if (!top_window || !ATSPI_IS_COMPONENT(top_window))
1171 DEBUG("No active window detected or no AtspiComponent interface available");
1175 rect = atspi_component_get_extents(ATSPI_COMPONENT(top_window), ATSPI_COORD_TYPE_SCREEN, &err);
1179 ERROR("Unable to fetch window screen coordinates");
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))
1187 DEBUG("Scroll don't start within active window borders");
1192 ret = atspi_component_get_accessible_at_point(ATSPI_COMPONENT(top_window), x, y, ATSPI_COORD_TYPE_SCREEN, &err);
1196 ERROR("Unable to get accessible objct at (%d, %d) screen coordinates.", x, y);
1201 // find accessible object with Scrollable interface
1202 while (ret && (ret != top_window))
1204 name = atspi_accessible_get_name(ret, &err);
1206 role = atspi_accessible_get_role_name(ret, &err);
1208 DEBUG("Testing for scrollability: %s %s",
1210 if (atspi_accessible_get_scrollable(ret))
1212 DEBUG("Scrollable widget found at (%d, %d), name: %s, role: %s", x, y,
1216 return ATSPI_SCROLLABLE(ret);
1220 ret = atspi_accessible_get_parent(ret, &err);
1223 ERROR("Unable to fetch AT-SPI parent");
1232 static void _widget_scroll_begin(Gesture_Info *gi)
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);
1243 ERROR("Failed to reset scroll context.");
1245 scrolled_obj = NULL;
1249 scrolled_obj = _find_scrollable_ancestor_at_xy(gi->x_begin, gi->y_begin);
1253 DEBUG("No scrollable widget found at (%d, %d) coordinates", gi->x_begin, gi->y_begin);
1257 atspi_scrollable_scroll_after_pointer(scrolled_obj, ATSPI_SCROLL_POINTER_START, gi->x_begin, gi->y_begin, &err);
1260 ERROR("Failed to initialize scroll operation");
1262 scrolled_obj = NULL;
1266 static void _widget_scroll_continue(Gesture_Info *gi)
1271 DEBUG("Scrolling context not initialized!");
1274 atspi_scrollable_scroll_after_pointer(scrolled_obj, ATSPI_SCROLL_POINTER_CONTINUE, gi->x_begin, gi->y_begin, &err);
1278 static void _widget_scroll_end(Gesture_Info *gi)
1283 ERROR("Scrolling context not initialized!");
1287 atspi_scrollable_scroll_after_pointer(scrolled_obj, ATSPI_SCROLL_POINTER_END, gi->x_begin, gi->y_begin, &err);
1288 scrolled_obj = NULL;
1293 static void _widget_scroll(Gesture_Info *gi)
1295 DEBUG("Recognized gesture state: %d", gi->state);
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;
1306 DEBUG("Scroll not finished yet");
1310 AtspiAccessible *obj = NULL;
1311 obj = flat_navi_context_current_get(context);
1314 ERROR("No context");
1318 AtspiStateSet *ss = atspi_accessible_get_state_set(obj);
1325 if (!atspi_state_set_contains(ss, ATSPI_STATE_SHOWING))
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)
1332 _focus_next_visible();
1334 else if (gesture_start_p.y < gi->y_end ||
1335 gesture_start_p.x < gi->x_end)
1338 _focus_prev_visible();
1343 g_object_unref(obj);
1346 static void _read_quickpanel(void )
1351 device_battery_get();
1352 device_bluetooth_get();
1353 device_signal_strenght_get();
1356 device_missed_events_get();
1360 static void _set_pause(void )
1364 Eina_Bool res = EINA_FALSE;
1365 bool pause = tts_pause_get();
1366 res = tts_pause_set(!pause);
1369 ERROR("Failed to set pause state");
1375 void auto_review_highlight_set(void)
1377 AtspiAccessible *obj = flat_navi_context_next(context);
1383 DEBUG("obj == NULL");
1384 s_auto_review.auto_review_on = false;
1387 else if(obj == flat_navi_context_last_get(context))
1389 DEBUG("obj == flat_navi_context_last_get()");
1390 s_auto_review.auto_review_on = false;
1394 _current_highlight_object_set(obj);
1399 void auto_review_highlight_top(void)
1402 char *text_to_speak = NULL;
1403 AtspiAccessible *obj = flat_navi_context_current_get(context);
1404 AtspiAccessible *first = flat_navi_context_first(context);
1408 _current_highlight_object_set(first);
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);
1422 static void _on_auto_review_stop(void)
1425 s_auto_review.auto_review_on = false;
1429 static void _on_utterance(void)
1432 DEBUG("s_auto_review.auto_review_on == %d", s_auto_review.auto_review_on);
1434 if(s_auto_review.auto_review_on)
1436 auto_review_highlight_set();
1442 static void _review_from_current(void)
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();
1453 static void _review_from_top()
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();
1465 _direct_scroll_back(void)
1467 DEBUG("ONE_FINGER_FLICK_LEFT_RETURN");
1470 ERROR("No navigation context created");
1474 AtspiAccessible *obj = NULL;
1475 AtspiAccessible *current = NULL;
1476 AtspiAccessible *parent = NULL;
1479 current = flat_navi_context_current_get(context);
1480 parent = atspi_accessible_get_parent (current, NULL);
1481 role = atspi_accessible_get_role(parent, NULL);
1483 if (role != ATSPI_ROLE_LIST)
1485 DEBUG("That operation can be done only on list, it is:%s", atspi_accessible_get_role_name(parent, NULL));
1489 int index = atspi_accessible_get_index_in_parent(current, NULL);
1490 int children_count = atspi_accessible_get_child_count(parent, NULL);
1492 if (children_count <=0)
1494 ERROR("NO visible element on list");
1498 DEBUG("start from element with index:%d/%d", index, children_count);
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);
1509 DEBUG("go back to %d element", index);
1510 obj = atspi_accessible_get_child_at_index (parent, index, NULL);
1516 DEBUG("Will set highlight and context");
1517 if (flat_navi_context_current_set(context, obj))
1519 DEBUG("current obj set");
1521 _current_highlight_object_set(obj);
1526 _direct_scroll_forward(void)
1528 DEBUG("ONE_FINGER_FLICK_RIGHT_RETURN");
1532 ERROR("No navigation context created");
1536 AtspiAccessible *obj = NULL;
1537 AtspiAccessible *current = NULL;
1538 AtspiAccessible *parent = NULL;
1541 current = flat_navi_context_current_get(context);
1542 parent = atspi_accessible_get_parent (current, NULL);
1543 role = atspi_accessible_get_role(parent, NULL);
1545 if (role != ATSPI_ROLE_LIST)
1547 DEBUG("That operation can be done only on list, it is:%s", atspi_accessible_get_role_name(parent, NULL));
1551 int index = atspi_accessible_get_index_in_parent(current, NULL);
1552 int children_count = atspi_accessible_get_child_count(parent, NULL);
1554 if (children_count <=0)
1556 ERROR("NO visible element on list");
1560 DEBUG("start from element with index:%d/%d", index, children_count);
1562 if (index >= children_count)
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);
1571 DEBUG("go back to %d element", index);
1572 obj = atspi_accessible_get_child_at_index (parent, index, NULL);
1578 DEBUG("Will set highlight and context");
1579 if (flat_navi_context_current_set(context, obj))
1581 DEBUG("current obj set");
1583 _current_highlight_object_set(obj);
1588 _direct_scroll_to_first(void)
1590 DEBUG("ONE_FINGER_FLICK_UP_RETURN");
1593 ERROR("No navigation context created");
1596 AtspiAccessible *obj = flat_navi_context_first(context);
1598 _current_highlight_object_set(obj);
1600 DEBUG("First widget not found. Abort");
1605 _direct_scroll_to_last(void)
1607 DEBUG("ONE_FINGER_FLICK_DOWN_RETURN");
1610 ERROR("No navigation context created");
1613 AtspiAccessible *obj = flat_navi_context_last(context);
1615 _current_highlight_object_set(obj);
1617 DEBUG("Last widget not found. Abort");
1625 AtspiAccessible *obj = NULL;
1635 AtspiValue *value = atspi_accessible_get_value_iface(obj);
1639 g_object_unref(value);
1647 _is_active_entry(void)
1653 ERROR("No navigation context created");
1656 AtspiAccessible *obj = NULL;
1658 obj = flat_navi_context_current_get(context);
1663 role = atspi_accessible_get_role(obj, NULL);
1664 if (role == ATSPI_ROLE_ENTRY)
1666 AtspiStateSet* state_set = atspi_accessible_get_state_set (obj);
1667 if (atspi_state_set_contains(state_set, ATSPI_STATE_FOCUSED))
1669 g_object_unref(state_set);
1672 g_object_unref(state_set);
1681 _is_slider(AtspiAccessible *obj)
1690 role = atspi_accessible_get_role(obj, NULL);
1691 if (role == ATSPI_ROLE_SLIDER)
1699 _move_slider(Gesture_Info *gi)
1701 DEBUG("ONE FINGER DOUBLE TAP AND HOLD");
1705 ERROR("No navigation context created");
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;
1725 if (!_is_slider(obj))
1727 ERROR("Object is not a slider");
1734 comp = atspi_accessible_get_component_iface(obj);
1737 ERROR("that slider do not have component interface");
1742 rect = atspi_component_get_extents(comp, ATSPI_COORD_TYPE_SCREEN, NULL);
1744 DEBUG("Current object is in:%d %d", rect->x, rect->y);
1745 DEBUG("Current object has size:%d %d", rect->width, rect->height);
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);
1756 DEBUG("SCROLLING but not meet counter:%d", counter)
1757 if (counter >= GESTURE_LIMIT)
1760 DEBUG("Scroll on point %d %d", gi->x_end, gi->y_end);
1761 continue_scroll(gi->x_end, gi->y_end);
1767 DEBUG("state == 2");
1768 end_scroll(gi->x_end, gi->y_end);
1770 value = atspi_accessible_get_value_iface(obj);
1774 g_object_unref(value);
1778 ERROR("There is not value interface in slider");
1784 AtspiAction *_get_main_window(void)
1786 AtspiAccessible *win = flat_navi_context_root_get(context);
1789 ERROR("win == NULL");
1793 AtspiAction *action = atspi_accessible_get_action_iface(win);
1796 ERROR("action == NULL");
1803 static int _find_action_index(AtspiAction *action, char *action_name_to_find)
1805 int action_num = atspi_action_get_n_actions(action, NULL);
1806 char *action_name = NULL;
1809 for(i = 0; i < action_num; ++i)
1811 action_name = atspi_action_get_action_name(action, i, NULL);
1813 if(!strcmp(action_name_to_find, action_name))
1824 static void _start_stop_signal_send(void)
1826 int action_index = -1;
1827 char *action_name = "pause_play";
1828 AtspiAction *action = _get_main_window();
1831 ERROR("Could not get the action inteface");
1836 ERROR("action == NULL");
1840 action_index = _find_action_index(action, action_name);
1841 if(action_index < 0)
1843 ERROR("Pause_play action not found");
1847 DEBUG("ACTION: %s has index: %d", action_name, action_index);
1848 atspi_action_do_action(action, action_index, NULL);
1851 static void on_gesture_detected(void *data, Gesture_Info *info)
1853 dbus_gesture_adapter_emit(info);
1854 _on_auto_review_stop();
1856 if (info->type == ONE_FINGER_SINGLE_TAP && info->state == 3)
1858 DEBUG("One finger single tap aborted");
1864 case ONE_FINGER_HOVER:
1867 DEBUG("Prepare to move slider");
1872 DEBUG("Will focus on object, slider is not ready");
1873 _focus_widget(info);
1876 case TWO_FINGERS_HOVER:
1877 _widget_scroll(info);
1879 case ONE_FINGER_FLICK_LEFT:
1882 case ONE_FINGER_FLICK_RIGHT:
1885 case ONE_FINGER_FLICK_UP:
1886 if (_is_active_entry())
1887 _caret_move_backward();
1888 else if (_has_value())
1893 case ONE_FINGER_FLICK_DOWN:
1894 if (_is_active_entry())
1895 _caret_move_forward();
1896 else if(_has_value())
1901 case ONE_FINGER_SINGLE_TAP:
1903 _focus_widget(info);
1905 case ONE_FINGER_DOUBLE_TAP:
1908 case TWO_FINGERS_SINGLE_TAP:
1911 case TWO_FINGERS_DOUBLE_TAP:
1912 _start_stop_signal_send();
1914 case TWO_FINGERS_TRIPLE_TAP:
1915 #ifdef SCREEN_READER_MOBILE
1919 case THREE_FINGERS_SINGLE_TAP:
1922 case THREE_FINGERS_DOUBLE_TAP:
1923 _review_from_current();
1925 case THREE_FINGERS_FLICK_DOWN:
1926 _quickpanel_change_state(QUICKPANEL_DOWN);
1928 case THREE_FINGERS_FLICK_UP:
1929 _quickpanel_change_state(QUICKPANEL_UP);
1931 case ONE_FINGER_FLICK_LEFT_RETURN:
1932 _direct_scroll_back();
1934 case ONE_FINGER_FLICK_RIGHT_RETURN:
1935 _direct_scroll_forward();
1937 case ONE_FINGER_FLICK_UP_RETURN:
1938 if (_is_active_entry())
1941 _direct_scroll_to_first();
1943 case ONE_FINGER_FLICK_DOWN_RETURN:
1944 if (_is_active_entry())
1947 _direct_scroll_to_last();
1950 DEBUG("Gesture type %d not handled in switch", info->type);
1955 _view_content_changed(AtspiAccessible *root, void *user_data)
1958 if (flat_navi_is_valid(context, root))
1960 flat_navi_context_free(context);
1961 context = flat_navi_context_create(root);
1962 _current_highlight_object_set(flat_navi_context_current_get(context));
1966 void clear(gpointer d)
1968 AtspiAccessible ** data = d;
1969 AtspiAccessible *obj = *data;
1970 g_object_unref(obj);
1973 static AtspiAccessible* _get_modal_descendant(AtspiAccessible *root)
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,
1982 ATSPI_Collection_MATCH_INVALID,
1984 ATSPI_Collection_MATCH_INVALID,
1986 ATSPI_Collection_MATCH_INVALID,
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,
1993 ATSPI_Collection_SORT_ORDER_INVALID,
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)
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);
2012 static void on_window_activate(void *data, AtspiAccessible *window)
2016 app_tracker_callback_unregister(top_window, _view_content_changed, NULL);
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);
2029 flat_navi_context_free(context);
2030 ERROR("No top window found!");
2032 top_window = window;
2036 void kb_tracker (void *data, Key k)
2047 DEBUG("Key %d not supported \n", k);
2051 void navigator_init(void)
2055 set_utterance_cb(_on_utterance);
2057 screen_reader_gestures_tracker_register(on_gesture_detected, NULL);
2058 // register on active_window
2059 dbus_gesture_adapter_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();
2068 keyboard_tracker_init();
2069 keyboard_tracker_register(kb_tracker, NULL);
2072 void navigator_shutdown(void)
2077 AtspiComponent *comp = atspi_accessible_get_component_iface(current_obj);
2080 atspi_component_clear_highlight(comp, &err);
2086 flat_navi_context_free(context);
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();
2096 keyboard_tracker_shutdown();