Structura navigation fixes.
authorLukasz Stanislawski <l.stanislaws@samsung.com>
Mon, 1 Dec 2014 18:42:30 +0000 (19:42 +0100)
committerLukasz Stanislawski <l.stanislaws@samsung.com>
Mon, 1 Dec 2014 18:42:30 +0000 (19:42 +0100)
ObjectCach fixes added. Fix typo in gesture signals.
Change TwoFinger flick into ThreeFinge flick for container navigation.

src/gesture_tracker.c
src/navigator.c
src/object_cache.c
src/position_sort.c
src/structural_navi.c

index 1db8d10..3d45446 100644 (file)
@@ -39,7 +39,7 @@ static Gesture gesture_name_to_enum (const char *gesture_name)
      return ONE_FINGER_FLICK_DOWN;
 
  if(!strcmp("ThreeFingersFlickLeft", gesture_name))
-     return THREE_FINGERS_FLICK_RIGHT;
+     return THREE_FINGERS_FLICK_LEFT;
 
  if(!strcmp("ThreeFingersFlickRight", gesture_name))
      return THREE_FINGERS_FLICK_RIGHT;
index dc62a23..46709e5 100644 (file)
@@ -27,7 +27,7 @@ _current_highlight_object_set(AtspiAccessible *obj)
 {
    if (!obj)
      {
-        atspi_component_clear_highlight(top_window);
+        if (top_window) atspi_component_clear_highlight(top_window);
         return;
      }
    if (current_obj == obj)
@@ -684,7 +684,10 @@ static void _goto_children_widget(void)
         return;
      }
    obj = structural_navi_level_down(current_obj);
-   if (obj) _current_highlight_object_set(obj);
+   if (obj)
+     _current_highlight_object_set(obj);
+   else
+     DEBUG("Unable to find hihglightable children widget");
 }
 
 static void _escape_children_widget(void)
@@ -696,7 +699,10 @@ static void _escape_children_widget(void)
         return;
      }
    obj = structural_navi_level_up(current_obj);
-   if (obj) _current_highlight_object_set(obj);
+   if (obj)
+     _current_highlight_object_set(obj);
+   else
+     DEBUG("Unable to find hihglightable parent widget");
 }
 
 static void _widget_scroll(Gesture_Info *gi)
@@ -745,10 +751,10 @@ static void on_gesture_detected(void *data, Gesture_Info *info)
       case ONE_FINGER_DOUBLE_TAP:
           _activate_widget();
           break;
-      case TWO_FINGERS_FLICK_LEFT:
+      case THREE_FINGERS_FLICK_LEFT:
           _escape_children_widget();
           break;
-      case TWO_FINGERS_FLICK_RIGHT:
+      case THREE_FINGERS_FLICK_RIGHT:
           _goto_children_widget();
           break;
       case THREE_FINGERS_FLICK_DOWN:
@@ -826,11 +832,13 @@ static void on_window_activate(void *data, AtspiAccessible *window)
 {
       ERROR("... on window activate ...");
       top_window = window;
+      AtspiAccessible *obj;
+
       if(top_window)
       {
           ERROR("Window name: %s", atspi_accessible_get_name(window, NULL));
-          current_obj = pivot_chooser_pivot_get(top_window);
-          if (!current_obj)
+          obj = pivot_chooser_pivot_get(top_window);
+          if (!obj)
           {
               ERROR("Unable to find pivot widget");
               return;
@@ -838,17 +846,18 @@ static void on_window_activate(void *data, AtspiAccessible *window)
           else
             {
                DEBUG("Found pivot widget: name: %s, role: %s",
-                     atspi_accessible_get_name(current_obj, NULL),
-                     atspi_accessible_get_role_name(current_obj, NULL));
+                     atspi_accessible_get_name(obj, NULL),
+                     atspi_accessible_get_role_name(obj, NULL));
             }
          _window_cache_builded = EINA_FALSE;
          object_cache_build_async(window, 5, _on_cache_builded, NULL);
+         _current_highlight_object_set(obj);
       }
       else
       {
           ERROR("No top window found!");
           top_window = NULL;
-          current_obj = NULL;
+          _current_highlight_object_set(NULL);
           scrolled_obj = NULL;
       }
 }
index 9dd1821..0b762d1 100644 (file)
@@ -93,8 +93,15 @@ _cache_item_construct(AtspiAccessible *obj)
         return NULL;
      }
 
-   if ((comp = atspi_accessible_get_component(obj)) != NULL)
+   comp = atspi_accessible_get_component(obj);
+   if (!comp) {
+     ERROR("Cached Object do not implement Component interface");
+   }
+   else {
       ret->bounds = atspi_component_get_extents(comp, ATSPI_COORD_TYPE_SCREEN, NULL);
+      DEBUG("Extents: %d %d %d %d", ret->bounds->x, ret->bounds->y, ret->bounds->width, ret->bounds->height);
+      g_object_unref(comp);
+   }
 
    return ret;
 }
@@ -115,7 +122,7 @@ _cache_item_n_cache(Eina_List *objs, int count)
         oc = _cache_item_construct(obj);
         if (!oc) break;
 
-        eina_hash_add(cache, obj, oc);
+        eina_hash_add(cache, &obj, oc);
         g_object_unref(obj);
      }
 
@@ -155,10 +162,7 @@ _do_cache(void *data)
 
    if (toprocess)
      idler = ecore_idler_add(_do_cache, NULL);
-   else if (callback)
-     {
-        callback(user_data);
-     }
+   else if (callback) callback(user_data);
 
    return EINA_FALSE;
 }
@@ -166,8 +170,6 @@ _do_cache(void *data)
 void
 object_cache_build_async(AtspiAccessible *root, int bulk_size, ObjectCacheReadyCb cb, void *ud)
 {
-   Eina_List *objs;
-
    _object_cache_free_internal();
 
    callback = cb;
@@ -181,8 +183,8 @@ object_cache_build_async(AtspiAccessible *root, int bulk_size, ObjectCacheReadyC
         return;
      }
 
-   objs = _cache_candidates_list_prepare(root);
-   idler = ecore_idler_add(_do_cache, objs);
+   toprocess = _cache_candidates_list_prepare(root);
+   idler = ecore_idler_add(_do_cache, NULL);
 
    return;
 }
@@ -197,6 +199,12 @@ const ObjectCache*
 object_cache_get(AtspiAccessible *obj)
 {
    ObjectCache *ret = NULL;
+   if (idler)
+     {
+        ERROR("Invalid usage. Async cache build is ongoing...");
+        return NULL;
+     }
+
    if (!cache)
      {
         cache = _object_cache_new();
@@ -206,14 +214,13 @@ object_cache_get(AtspiAccessible *obj)
              return NULL;
           }
      }
-   else
-      ret = eina_hash_find(cache, obj);
 
-   if (!ret && !idler)
+   ret = eina_hash_find(cache, &obj);
+   if (!ret)
      {
         // fallback to blocking d-bus call
         ret = _cache_item_construct(obj);
-        eina_hash_add(cache, obj, ret);
+        eina_hash_add(cache, &obj, ret);
      }
 
    return ret;
index dc084b2..7dacd27 100644 (file)
@@ -15,7 +15,12 @@ _sort_by_y_cb(const void *a, const void *b)
    cA = object_cache_get(objA);
    cB = object_cache_get(objB);
 
-   return cA->bounds->y < cB->bounds->y;
+   if (cA->bounds->y == cB->bounds->y)
+     return 0;
+   else if (cA->bounds->y > cB->bounds->y)
+     return 1;
+   else
+     return -1;
 }
 
 static int
@@ -30,7 +35,12 @@ _sort_by_x_cb(const void *a, const void *b)
    cA = object_cache_get(objA);
    cB = object_cache_get(objB);
 
-   return cA->bounds->x < cB->bounds->x;
+   if (cA->bounds->x == cB->bounds->x)
+     return 0;
+   else if (cA->bounds->x > cB->bounds->x)
+     return 1;
+   else
+     return -1;
 }
 
 static Eina_List*
@@ -38,19 +48,30 @@ _get_zones(const Eina_List *objs)
 {
    Eina_List *candidates = NULL, *l;
    AtspiAccessible *obj;
+   AtspiComponent *comp;
    const ObjectCache *oc;
 
    EINA_LIST_FOREACH(objs, l, obj)
      {
-        if (atspi_accessible_get_component(obj))
+        if ((comp = atspi_accessible_get_component(obj)) != NULL)
           {
              oc = object_cache_get(obj);
+
              // some objects may implement AtspiCompoment interface, however
              // they do not have valid sizes.
-             if ((oc->bounds->width < 0) || oc->bounds->height < 0)
-               continue;
+             if (!oc->bounds || (oc->bounds->width < 0) || oc->bounds->height < 0)
+               {
+                  DEBUG("Invalid bounds. skipping from zone list: %s %s",
+                   atspi_accessible_get_name(obj, NULL),
+                   atspi_accessible_get_role_name(obj, NULL));
+                  continue;
+               }
              candidates = eina_list_append(candidates, obj);
           }
+        else
+          DEBUG("No component interface: skipping %s %s",
+                atspi_accessible_get_name(obj, NULL),
+                atspi_accessible_get_role_name(obj, NULL));
      }
 
    // Sort object by y - coordinate
@@ -76,33 +97,47 @@ _get_lines(const Eina_List *objs)
         const ObjectCache *oc = object_cache_get(obj);
         // Object are considered as present in same line, if
         // its y coordinate begins maximum 25% below
-        // y coordinate of first object in line.
-        if ((line_beg->bounds->y + 0.25 * line_beg->bounds->height) >
+        // y coordinate% of first object in line.
+        if ((line_beg->bounds->y + (int)(0.25 * (double)line_beg->bounds->height)) >
             oc->bounds->y)
           {
              line = eina_list_append(line, obj);
              continue;
           }
-        lines = eina_list_append(lines, line);
-        line = NULL;
+        else
+          {
+             //finish line & set new line leader
+             lines = eina_list_append(lines, line);
+             line = NULL;
+             line = eina_list_append(line, obj);
+             line_beg = object_cache_get(obj);
+          }
      }
 
+   // finish last line
+   if (line) lines = eina_list_append(lines, line);
+
    return lines;
 }
 
 Eina_List *position_sort(const Eina_List *objs)
 {
    Eina_List *l, *line, *zones, *lines = NULL;
+   int i = 0;
 
    // Get list of objects occupying place on the screen
+   DEBUG("PositionSort: Candidates; %d", eina_list_count(objs));
    zones = _get_zones(objs);
 
    // Cluster all zones into lines - verticaly
+   DEBUG("PositionSort: Zones; %d", eina_list_count(zones));
    lines = _get_lines(zones);
 
    // sort all zones in line - horizontaly
+   DEBUG("PositionSort: Lines; %d", eina_list_count(lines));
    EINA_LIST_FOREACH(lines, l, line)
      {
+        DEBUG("PositionSort: Line %d: %d items", i++, eina_list_count(line));
         line = eina_list_sort(line, 0, _sort_by_x_cb);
         eina_list_data_set(l, line);
      }
index 6337f7e..5b59148 100644 (file)
@@ -1,11 +1,53 @@
 #include "structural_navi.h"
+#include "position_sort.h"
 #include "logger.h"
 
+static Eina_List*
+_atspi_children_list_get(AtspiAccessible *parent)
+{
+   Eina_List *ret = NULL;
+   int count = atspi_accessible_get_child_count(parent, NULL);
+   int i;
+
+   for (i = 0; i < count; i++)
+     {
+        AtspiAccessible *child = atspi_accessible_get_child_at_index(parent, i, NULL);
+        if (child) ret = eina_list_append(ret, child);
+     }
+
+   return ret;
+}
+
+static void
+_atspi_children_list_free(Eina_List *children)
+{
+   AtspiAccessible *obj;
+
+   EINA_LIST_FREE(children, obj)
+      g_object_unref(obj);
+}
+
+static Eina_List*
+_flat_review_get(Eina_List *tosort)
+{
+   Eina_List *ret = NULL, *lines, *l, *line;
+
+   lines = position_sort(tosort);
+
+   EINA_LIST_FOREACH(lines, l, line)
+     {
+        ret = eina_list_merge(ret, line);
+     }
+
+   eina_list_free(lines);
+
+   return ret;
+}
+
 AtspiAccessible *structural_navi_same_level_next(AtspiAccessible *current)
 {
     AtspiAccessible *parent;
     AtspiRole role;
-    int id, n;
 
     parent = atspi_accessible_get_parent(current, NULL);
     if (!parent) return NULL;
@@ -13,11 +55,16 @@ AtspiAccessible *structural_navi_same_level_next(AtspiAccessible *current)
     role = atspi_accessible_get_role(parent, NULL);
     if (role != ATSPI_ROLE_DESKTOP_FRAME)
       {
-         n = atspi_accessible_get_child_count(parent, NULL);
-         id = atspi_accessible_get_index_in_parent(current, NULL);
-         if (id == (n - 1)) DEBUG("End of children structure list reached.");
-         id = (id + 1) == n ? id : id + 1;
-         return atspi_accessible_get_child_at_index(parent, id, NULL);
+         Eina_List *children = _atspi_children_list_get(parent);
+         Eina_List *me = eina_list_data_find_list(children, current);
+         Eina_List *sorted = _flat_review_get(children);
+         me = eina_list_data_find_list(sorted, current);
+         AtspiAccessible *ret = eina_list_data_get(eina_list_next(me));
+
+         eina_list_free(sorted);
+         _atspi_children_list_free(children);
+
+         return ret;
       }
     return NULL;
 }
@@ -26,7 +73,6 @@ AtspiAccessible *structural_navi_same_level_prev(AtspiAccessible *current)
 {
     AtspiAccessible *parent;
     AtspiRole role;
-    int id;
 
     parent = atspi_accessible_get_parent(current, NULL);
     if (!parent) return NULL;
@@ -34,10 +80,15 @@ AtspiAccessible *structural_navi_same_level_prev(AtspiAccessible *current)
     role = atspi_accessible_get_role(parent, NULL);
     if (role != ATSPI_ROLE_DESKTOP_FRAME)
       {
-         id = atspi_accessible_get_index_in_parent(current, NULL);
-         if (id == 0) DEBUG("Begining of children structure list reached.");
-         id = id  == 0 ? id : id - 1;
-         return atspi_accessible_get_child_at_index(parent, id, NULL);
+         Eina_List *children = _atspi_children_list_get(parent);
+         Eina_List *sorted = _flat_review_get(children);
+         Eina_List *me = eina_list_data_find_list(sorted, current);
+         AtspiAccessible *ret = eina_list_data_get(eina_list_prev(me));
+
+         eina_list_free(sorted);
+         _atspi_children_list_free(children);
+
+         return ret;
       }
     return NULL;
 }
@@ -60,10 +111,17 @@ AtspiAccessible *structural_navi_level_up(AtspiAccessible *current)
 
 AtspiAccessible *structural_navi_level_down(AtspiAccessible *current)
 {
-    int n = atspi_accessible_get_child_count(current, NULL);
-    if (!n) return NULL;
+   AtspiAccessible *ret;
+
+   Eina_List *children = _atspi_children_list_get(current);
+   Eina_List *sorted = _flat_review_get(children);
 
-    return atspi_accessible_get_child_at_index(current, 0, NULL);
+   ret = eina_list_data_get(sorted);
+
+   eina_list_free(sorted);
+   _atspi_children_list_free(children);
+
+   return ret;
 }
 
 static AtspiAccessible*