[access] support back gesture
[framework/uifw/elementary.git] / src / lib / elm_access.c
index 652c29d..f72f897 100644 (file)
@@ -1,5 +1,6 @@
 #include <Elementary.h>
 #include "elm_priv.h"
+#include "elm_interface_scrollable.h"
 
 static const char ACCESS_SMART_NAME[] = "elm_access";
 
@@ -25,6 +26,9 @@ typedef struct _Action_Info Action_Info;
 
 static Eina_Bool mouse_event_enable = EINA_TRUE;
 static Eina_Bool read_mode = EINA_FALSE;
+static Evas_Coord_Point offset;
+static Evas_Object *s_parent; /* scrollable parent */
+static Elm_Access_Action_Type action_type = ELM_ACCESS_ACTION_FIRST;
 
 static Evas_Object * _elm_access_add(Evas_Object *parent);
 
@@ -73,6 +77,10 @@ _elm_access_smart_activate(Evas_Object *obj, Elm_Activate act)
       case ELM_ACTIVATE_LEFT:
         break;
 
+      case ELM_ACTIVATE_BACK:
+        type = ELM_ACCESS_ACTION_BACK;
+        break;
+
       default:
         break;
      }
@@ -449,6 +457,73 @@ _elm_access_widget_item_access_order_unset(Elm_Widget_Item *item)
      }
 }
 
+void
+_elm_access_highlight_object_scroll(Evas_Object *obj, int type, int x, int y)
+{
+   Evas *evas;
+   Evas_Object *ho;
+   Evas_Coord_Rectangle ho_area;
+
+   if (!obj) return;
+
+   evas = evas_object_evas_get(obj);
+   if (!evas) return;
+
+   switch (type)
+     {
+      case 0:
+        ho = _access_highlight_object_get(obj);
+        if (!ho)
+          {
+             s_parent = NULL;
+             return;
+          }
+        else
+          {
+             /* find scrollable parent */
+             s_parent = elm_widget_parent_get(ho);
+             while (s_parent)
+               {
+                  if(!!evas_object_smart_interface_get(s_parent, ELM_SCROLLABLE_IFACE_NAME))
+                    break;
+                  s_parent = elm_widget_parent_get(s_parent);
+               }
+
+              if (!s_parent) return;
+
+              ELM_SCROLLABLE_IFACE_GET(s_parent, s_iface);
+              s_iface->repeat_events_set(s_parent, EINA_FALSE);
+
+              evas_object_geometry_get
+                (ho, &ho_area.x, &ho_area.y, &ho_area.w, &ho_area.h);
+
+              offset.x = x - (ho_area.x + (ho_area.w / 2));
+              offset.y = y - (ho_area.y + (ho_area.h / 2));
+          }
+
+        evas_event_feed_mouse_in(evas, 0, NULL);
+        evas_event_feed_mouse_move(evas, x - offset.x, y - offset.y, 0, NULL);
+        evas_event_feed_mouse_down(evas, 1, EVAS_BUTTON_NONE, 0, NULL);
+        break;
+
+      case 1:
+        if (!s_parent) return;
+        evas_event_feed_mouse_move(evas, x - offset.x, y - offset.y, 0, NULL);
+        break;
+
+      case 2:
+        if (!s_parent) return;
+        evas_event_feed_mouse_up(evas, 1, EVAS_BUTTON_NONE, 0, NULL);
+
+        ELM_SCROLLABLE_IFACE_GET(s_parent, s_iface);
+        s_iface->repeat_events_set(s_parent, EINA_TRUE);
+        break;
+
+      default:
+        break;
+     }
+}
+
 static Eina_Bool
 _access_action_callback_call(Evas_Object *obj,
                              Elm_Access_Action_Type type,
@@ -509,8 +584,13 @@ _access_highlight_next_get(Evas_Object *obj, Elm_Focus_Direction dir)
 
         if (!_access_action_callback_call(ho, type, NULL))
           {
+             /* change highlight object */
+             action_type = type;
+
              _elm_access_highlight_set(target);
              ret = EINA_FALSE;
+
+             action_type = ELM_ACCESS_ACTION_FIRST;
           }
      }
 
@@ -518,12 +598,15 @@ _access_highlight_next_get(Evas_Object *obj, Elm_Focus_Direction dir)
 
    return ret;
 }
+
 //-------------------------------------------------------------------------//
 EAPI void
 _elm_access_highlight_set(Evas_Object* obj)
 {
+   Evas *evas;
    Elm_Access_Info *ac;
    Evas_Object *ho;
+   Evas_Coord_Point ho_point = { 0, 0 };
 
    if (!obj) return;
 
@@ -534,6 +617,15 @@ _elm_access_highlight_set(Evas_Object* obj)
    if (!ac) return;
 
    _access_highlight_read(ac, obj);
+
+   /* move mouse position to inside of highlight object. if an object has a
+      highlight by highlight_cycle();, the mouse still positions at previous
+      position which would be made by MOUSE_IN event. */
+   evas = evas_object_evas_get(obj);
+   if (!evas) return;
+
+   evas_object_geometry_get(obj, &ho_point.x, &ho_point.y, 0, 0);
+   evas_event_feed_mouse_move(evas, ho_point.x, ho_point.y, 0, NULL);
 }
 
 EAPI void
@@ -562,6 +654,7 @@ _elm_access_text_set(Elm_Access_Info *ac, int type, const char *text)
 {
    Elm_Access_Item *ai = _access_add_set(ac, type);
    if (!ai) return;
+   ai->func = NULL;
    ai->data = eina_stringshare_add(text);
 }
 
@@ -597,17 +690,32 @@ _elm_access_activate_callback_set(Elm_Access_Info           *ac,
 EAPI void
 _elm_access_highlight_object_activate(Evas_Object *obj, Elm_Activate act)
 {
-   Evas_Object *highlight;
+   Evas_Object *ho;
 
-   highlight = _access_highlight_object_get(obj);
-   if (!highlight) return;
+   ho = _access_highlight_object_get(obj);
+   if (!ho) return;
 
-   _elm_access_read_mode_set(EINA_FALSE);
+   switch (act)
+     {
+      case ELM_ACTIVATE_DEFAULT:
+      case ELM_ACTIVATE_UP:
+      case ELM_ACTIVATE_DOWN:
+        _elm_access_read_mode_set(EINA_FALSE);
+
+        if (!elm_object_focus_get(ho))
+        elm_object_focus_set(ho, EINA_TRUE);
 
-   if (!elm_object_focus_get(highlight))
-     elm_object_focus_set(highlight, EINA_TRUE);
+        elm_widget_activate(ho, act);
+        break;
+
+      case ELM_ACTIVATE_BACK:
+        elm_widget_activate(ho, act);
+        break;
+
+      default:
+        break;
+     }
 
-   elm_widget_activate(highlight, act);
    return;
 }
 
@@ -643,9 +751,13 @@ _elm_access_highlight_cycle(Evas_Object *obj, Elm_Focus_Direction dir)
    else
      type = ELM_ACCESS_ACTION_HIGHLIGHT_PREV;
 
+   action_type = type;
+
    if (!_access_action_callback_call(ho, type, NULL))
      elm_widget_focus_cycle(obj, dir);
 
+   action_type = ELM_ACCESS_ACTION_FIRST;
+
    _elm_access_read_mode_set(EINA_FALSE);
 }
 
@@ -729,6 +841,7 @@ _elm_access_object_hilight(Evas_Object *obj)
 {
    Evas_Object *o;
    Evas_Coord x, y, w, h;
+   Elm_Access_Action_Info *a;
 
    o = evas_object_name_find(evas_object_evas_get(obj), "_elm_access_disp");
    if (!o)
@@ -753,6 +866,7 @@ _elm_access_object_hilight(Evas_Object *obj)
                                                  _access_obj_hilight_move_cb, NULL);
              evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_RESIZE,
                                                  _access_obj_hilight_resize_cb, NULL);
+             _access_action_callback_call(ptarget, ELM_ACCESS_ACTION_UNHIGHLIGHT, NULL);
           }
      }
    evas_object_data_set(o, "_elm_access_target", obj);
@@ -775,10 +889,13 @@ _elm_access_object_hilight(Evas_Object *obj)
 
    /* use callback, should an access object do below every time when
        * a window gets a client message ECORE_X_ATOM_E_ILLMUE_ACTION_READ? */
-   if (!_access_action_callback_call(obj, ELM_ACCESS_ACTION_HIGHLIGHT, NULL))
+   a = calloc(1, sizeof(Elm_Access_Action_Info));
+   a->action_type = action_type;
+   if (!_access_action_callback_call(obj, ELM_ACCESS_ACTION_HIGHLIGHT, a))
      evas_object_show(o);
    else
      evas_object_hide(o);
+   free(a);
 }
 
 EAPI void
@@ -801,6 +918,7 @@ _elm_access_object_unhilight(Evas_Object *obj)
                                             _access_obj_hilight_resize_cb, NULL);
         evas_object_del(o);
         elm_widget_parent_highlight_set(ptarget, EINA_FALSE);
+        _access_action_callback_call(ptarget, ELM_ACCESS_ACTION_UNHIGHLIGHT, NULL);
      }
 }
 
@@ -1165,12 +1283,14 @@ EAPI Eina_Bool
 elm_access_action(Evas_Object *obj, const Elm_Access_Action_Type type, void *action_info)
 {
    Evas *evas;
+   Evas_Object *ho;
    Elm_Access_Action_Info *a;
 
    a = (Elm_Access_Action_Info *) action_info;
 
    switch (type)
      {
+      case ELM_ACCESS_ACTION_READ:
       case ELM_ACCESS_ACTION_HIGHLIGHT:
         evas = evas_object_evas_get(obj);
         if (!evas) return EINA_FALSE;
@@ -1178,9 +1298,15 @@ elm_access_action(Evas_Object *obj, const Elm_Access_Action_Type type, void *act
         _elm_access_mouse_event_enabled_set(EINA_TRUE);
 
         evas_event_feed_mouse_in(evas, 0, NULL);
-        evas_event_feed_mouse_move(evas, a->x1, a->y1, 0, NULL);
-
+        evas_event_feed_mouse_move(evas, a->x, a->y, 0, NULL);
         _elm_access_mouse_event_enabled_set(EINA_FALSE);
+
+        ho = _access_highlight_object_get(obj);
+        if (ho)
+          _access_action_callback_call(ho, ELM_ACCESS_ACTION_READ, a);
+        break;
+
+      case ELM_ACCESS_ACTION_UNHIGHLIGHT:
         break;
 
       case ELM_ACCESS_ACTION_HIGHLIGHT_NEXT:
@@ -1206,6 +1332,7 @@ elm_access_action(Evas_Object *obj, const Elm_Access_Action_Type type, void *act
         break;
 
       case ELM_ACCESS_ACTION_SCROLL:
+        _elm_access_highlight_object_scroll(obj, a->mouse_type, a->x, a->y);
         break;
 
       case ELM_ACCESS_ACTION_BACK: