[access][plug] add access feature
authorShinwoo Kim <cinoo.kim@samsung.com>
Tue, 16 Apr 2013 08:33:11 +0000 (17:33 +0900)
committerSungho Kwak <sungho1.kwak@samsung.com>
Mon, 29 Apr 2013 11:29:40 +0000 (20:29 +0900)
src/lib/elm_access.c
src/lib/elm_access.h
src/lib/elm_conform.c
src/lib/elm_plug.c
src/lib/elm_plug.h

index 35ca4e2..167ccda 100644 (file)
@@ -28,7 +28,7 @@ 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 Elm_Access_Action_Type action_by = ELM_ACCESS_ACTION_FIRST;
 
 static Evas_Object * _elm_access_add(Evas_Object *parent);
 
@@ -64,11 +64,11 @@ _elm_access_smart_activate(Evas_Object *obj, Elm_Activate act)
         break;
 
       case ELM_ACTIVATE_UP:
-        type = ELM_ACCESS_ACTION_VALUE_CHANGE;
+        type = ELM_ACCESS_ACTION_UP;
         break;
 
       case ELM_ACTIVATE_DOWN:
-        type = ELM_ACCESS_ACTION_VALUE_CHANGE;
+        type = ELM_ACCESS_ACTION_DOWN;
         break;
 
       case ELM_ACTIVATE_RIGHT:
@@ -501,16 +501,27 @@ _elm_access_highlight_object_scroll(Evas_Object *obj, int type, int x, int y)
 static Eina_Bool
 _access_action_callback_call(Evas_Object *obj,
                              Elm_Access_Action_Type type,
-                             void *data)
+                             Elm_Access_Action_Info *action_info)
 {
+   Elm_Access_Action_Info *ai = NULL;
    Action_Info *a;
    Eina_Bool ret;
 
    ret = EINA_FALSE;
    a = evas_object_data_get(obj, "_elm_access_action_info");
 
+   if (!action_info)
+     {
+        ai = calloc(1, sizeof(Elm_Access_Action_Info));
+        action_info = ai;
+     }
+
+   action_info->action_type = type;
+
    if (a && (a->fn[type].cb))
-     ret = a->fn[type].cb(a->fn[type].user_data, obj, data);
+     ret = a->fn[type].cb(a->fn[type].user_data, obj, action_info);
+
+   if (ai) free(ai);
 
    return ret;
 }
@@ -558,12 +569,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;
+             /* this value is used in _elm_access_object_highlight();
+                to inform the target object of how to get highlight */
+             action_by = type;
 
              _elm_access_highlight_set(target);
 
-             action_type = ELM_ACCESS_ACTION_FIRST;
+             action_by = ELM_ACCESS_ACTION_FIRST;
           }
      }
 
@@ -724,12 +736,12 @@ _elm_access_highlight_cycle(Evas_Object *obj, Elm_Focus_Direction dir)
    else
      type = ELM_ACCESS_ACTION_HIGHLIGHT_PREV;
 
-   action_type = type;
+   action_by = type;
 
    if (!_access_action_callback_call(ho, type, NULL))
      elm_widget_focus_cycle(obj, dir);
 
-   action_type = ELM_ACCESS_ACTION_FIRST;
+   action_by = ELM_ACCESS_ACTION_FIRST;
 
    _elm_access_read_mode_set(EINA_FALSE);
 }
@@ -863,7 +875,7 @@ _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? */
    a = calloc(1, sizeof(Elm_Access_Action_Info));
-   a->action_type = action_type;
+   a->action_by = action_by;
    if (!_access_action_callback_call(obj, ELM_ACCESS_ACTION_HIGHLIGHT, a))
      evas_object_show(o);
    else
@@ -1312,10 +1324,14 @@ elm_access_action(Evas_Object *obj, const Elm_Access_Action_Type type, void *act
         _elm_access_highlight_object_activate(obj, ELM_ACTIVATE_DEFAULT);
         break;
 
-      case ELM_ACCESS_ACTION_VALUE_CHANGE:
+      case ELM_ACCESS_ACTION_UP:
         _elm_access_highlight_object_activate(obj, ELM_ACTIVATE_UP);
         break;
 
+      case ELM_ACCESS_ACTION_DOWN:
+        _elm_access_highlight_object_activate(obj, ELM_ACTIVATE_DOWN);
+        break;
+
       case ELM_ACCESS_ACTION_SCROLL:
         _elm_access_highlight_object_scroll(obj, a->mouse_type, a->x, a->y);
         break;
index 667b18b..72138d2 100644 (file)
@@ -6,6 +6,8 @@
  *
  */
 
+#define MSG_DOMAIN_CONTROL_ACCESS (int)ECORE_X_ATOM_E_ILLUME_ACCESS_CONTROL
+
 enum _Elm_Access_Info_Type
 {
    ELM_ACCESS_INFO_FIRST = -1,
@@ -50,9 +52,11 @@ enum _Elm_Access_Action_Type
    ELM_ACCESS_ACTION_HIGHLIGHT_NEXT, /* set highlight to next object */
    ELM_ACCESS_ACTION_HIGHLIGHT_PREV, /* set highlight to previous object */
    ELM_ACCESS_ACTION_ACTIVATE, /* activate a highlight object */
-   ELM_ACCESS_ACTION_VALUE_CHANGE, /* change value of highlight object */
+   ELM_ACCESS_ACTION_VALUE_CHANGE, /* TODO: deprecate this */
    ELM_ACCESS_ACTION_SCROLL, /* scroll if one of highlight object parents
                               * is scrollable */
+   ELM_ACCESS_ACTION_UP, /* change value up of highlight object */
+   ELM_ACCESS_ACTION_DOWN, /* change value down of highlight object */
    ELM_ACCESS_ACTION_BACK, /* go back to a previous view
                               ex: pop naviframe item */
    ELM_ACCESS_ACTION_READ, /* highlight an object */
@@ -74,6 +78,7 @@ struct _Elm_Access_Action_Info
                                2: mouse up   */
 
    Elm_Access_Action_Type action_type;
+   Elm_Access_Action_Type action_by;
    Eina_Bool              highlight_cycle : 1;
 };
 
index b2b359d..66250db 100644 (file)
@@ -393,20 +393,30 @@ static const char PLUG_KEY[] = "__Plug_Ecore_Evas";
 #define MSG_ID_INDICATOR_TYPE 0X1005
 
 static void
-_plug_msg_handle(Ecore_Evas *ee, int msg_domain, int msg_id, void *data, int size)
+_plug_msg_handle(void *data, Evas_Object *obj, void *event_info)
 {
-   Evas_Object *conformant;
+   Evas_Object *conformant = data;
+   Elm_Plug_Message *pm = event_info;
+   int msg_domain = 0;
+   int msg_id = 0;
+   void *msg_data = NULL;
+   int msg_data_size = 0;
+
+   if (!conformant) return;
+   ELM_CONFORMANT_CHECK(conformant) ;
+   ELM_CONFORMANT_DATA_GET(conformant, sd);
+   msg_domain = pm->msg_domain;
+   msg_id = pm->msg_id;
+   msg_data = pm->data;
+   msg_data_size = pm->size;
 
-   if (!data) return;
-   DBG("Receive msg from plug ee=%p msg_domain=%x msg_id=%x size=%d", ee, msg_domain, msg_id, size);
+   DBG("Receive msg from plug msg_domain=%x msg_id=%x size=%d", msg_domain, msg_id, msg_data_size);
    //get plug object form ee
-   conformant = (Evas_Object *)ecore_evas_data_get(ee, CONFORMANT_KEY);
-   ELM_CONFORMANT_DATA_GET(conformant, sd);
    if (msg_domain == MSG_DOMAIN_CONTROL_INDICATOR)
      {
         if (msg_id == MSG_ID_INDICATOR_REPEAT_EVENT)
           {
-              int *repeat = data;
+              int *repeat = msg_data;
               DBG("Receive repeat event change message:(%d)", *repeat);
               if (1 == *repeat)
                 evas_object_repeat_events_set(sd->landscape_indicator, EINA_TRUE);
@@ -415,7 +425,7 @@ _plug_msg_handle(Ecore_Evas *ee, int msg_domain, int msg_id, void *data, int siz
           }
         if (msg_id == MSG_ID_INDICATOR_TYPE)
           {
-             Elm_Win_Indicator_Type_Mode *indi_t_mode = data;
+             Elm_Win_Indicator_Type_Mode *indi_t_mode = msg_data;
              Evas_Object *win = elm_widget_top_get(conformant);
              DBG("Receive indicator type change message:(%d)", *indi_t_mode);
              elm_win_indicator_type_set(win, *indi_t_mode);
@@ -453,13 +463,10 @@ _create_portrait_indicator(Evas_Object *obj)
      }
 
    //callback to deal with extn socket message
-   indicator_ee = ecore_evas_object_ecore_evas_get(elm_plug_image_object_get(port_indicator));
-   DBG("This is portrait indicator's ee=%p.", indicator_ee);
-   ecore_evas_callback_msg_handle_set(indicator_ee, _plug_msg_handle);
-   ecore_evas_data_set(indicator_ee, CONFORMANT_KEY, obj);
+   evas_object_smart_callback_add(port_indicator, "message.received", _plug_msg_handle, obj);
 
    DBG("The rotation value of portrait indicator was changed:(%d)", sd->rot);
-   ecore_evas_msg_parent_send(indicator_ee, MSG_DOMAIN_CONTROL_INDICATOR, MSG_ID_INDICATOR_ROTATION, &(sd->rot), sizeof(int));
+   elm_plug_msg_send(port_indicator, MSG_DOMAIN_CONTROL_INDICATOR, MSG_ID_INDICATOR_ROTATION, &(sd->rot), sizeof(int));
 
    elm_widget_sub_object_add(obj, port_indicator);
    evas_object_smart_callback_add(port_indicator, "image.deleted", _port_indicator_disconnected, obj);
@@ -500,12 +507,10 @@ _create_landscape_indicator(Evas_Object *obj)
      }
 
    //callback to deal with extn socket message
-   indicator_ee = ecore_evas_object_ecore_evas_get(elm_plug_image_object_get(land_indicator));
-   ecore_evas_data_set(indicator_ee, CONFORMANT_KEY, obj);
-   DBG("This is landscape indicator's ee=%p.", indicator_ee);
-   ecore_evas_callback_msg_handle_set(indicator_ee, _plug_msg_handle);
+   evas_object_smart_callback_add(land_indicator, "message.received", _plug_msg_handle, obj);
    DBG("The rotation value of landscape indicator was changed:(%d)", sd->rot);
-   ecore_evas_msg_parent_send(indicator_ee, MSG_DOMAIN_CONTROL_INDICATOR, MSG_ID_INDICATOR_ROTATION, &(sd->rot), sizeof(int));
+
+   elm_plug_msg_send(land_indicator, MSG_DOMAIN_CONTROL_INDICATOR, MSG_ID_INDICATOR_ROTATION, &(sd->rot), sizeof(int));
 
    elm_widget_sub_object_add(obj, land_indicator);
    evas_object_smart_callback_add(land_indicator, "image.deleted",_land_indicator_disconnected, obj);
@@ -1020,9 +1025,15 @@ _elm_conformant_smart_del(Evas_Object *obj)
    if (sd->port_indi_timer) ecore_timer_del(sd->port_indi_timer);
    if (sd->land_indi_timer) ecore_timer_del(sd->land_indi_timer);
    if (sd->portrait_indicator)
-     evas_object_del(sd->portrait_indicator);
+     {
+        evas_object_smart_callback_del(sd->portrait_indicator, "message.received", _plug_msg_handle);
+        evas_object_del(sd->portrait_indicator);
+     }
    if (sd->landscape_indicator)
-     evas_object_del(sd->landscape_indicator);
+     {
+        evas_object_smart_callback_del(sd->landscape_indicator, "message.received", _plug_msg_handle);
+        evas_object_del(sd->landscape_indicator);
+     }
    top = elm_widget_top_get(obj);
    evas_object_data_set(top, "\377 elm,conformant", NULL);
 
index 63666bc..800136a 100644 (file)
@@ -8,9 +8,11 @@ static const char PLUG_KEY[] = "__Plug_Ecore_Evas";
 
 static const char SIG_CLICKED[] = "clicked";
 static const char SIG_IMAGE_DELETED[] = "image.deleted";
+static const char SIG_MESSAGE_RECEIVED[] = "message.received";
 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
    {SIG_CLICKED, ""},
    {SIG_IMAGE_DELETED, ""},
+   {SIG_MESSAGE_RECEIVED, ""},
    {NULL, NULL}
 };
 
@@ -50,6 +52,64 @@ _elm_plug_smart_theme(Evas_Object *obj)
    return EINA_TRUE;
 }
 
+static Eina_Bool
+_access_action_release_cb(void *data __UNUSED__,
+                          Evas_Object *obj __UNUSED__,
+                          void *action_info __UNUSED__)
+{
+   return EINA_FALSE;
+}
+
+static void
+_elm_plug_ecore_evas_msg_handle(Ecore_Evas *ee, int msg_domain, int msg_id, void *data, int size)
+{
+   Evas_Object *plug, *parent;
+   Elm_Plug_Message pm;
+
+   if (!data) return;
+   DBG("Elm plug receive msg from socket ee=%p msg_domain=%x msg_id=%x size=%d", ee, msg_domain, msg_id, size);
+   //get plug object form ee
+   plug = (Evas_Object *)ecore_evas_data_get(ee, PLUG_KEY);
+   ELM_PLUG_CHECK(plug);
+   pm.msg_domain = msg_domain;
+   pm.msg_id = msg_id;
+   pm.data = data;
+   pm.size = size;
+
+   evas_object_smart_callback_call(plug, SIG_MESSAGE_RECEIVED, &pm);
+
+   /* get message from parent */
+   if (msg_domain == MSG_DOMAIN_CONTROL_ACCESS)
+     {
+        if (msg_id == ELM_ACCESS_ACTION_HIGHLIGHT_NEXT ||
+            msg_id == ELM_ACCESS_ACTION_HIGHLIGHT_PREV)
+          {
+             elm_access_action_cb_set(plug, msg_id,
+               _access_action_release_cb, NULL);
+
+             parent = plug;
+             do
+               {
+                  ELM_WIDGET_DATA_GET(parent, sd);
+                  if (sd->highlight_root)
+                    {
+                       /* change highlight root */
+                       plug = parent;
+                       break;
+                    }
+                 plug = parent;
+                 parent = elm_widget_parent_get(parent);
+               }
+             while (parent);
+
+             if (msg_id == ELM_ACCESS_ACTION_HIGHLIGHT_NEXT)
+                _elm_access_highlight_cycle(plug, ELM_FOCUS_NEXT);
+             else
+                _elm_access_highlight_cycle(plug, ELM_FOCUS_PREVIOUS);
+          }
+     }
+}
+
 static void
 _on_mouse_up(void *data,
              Evas *e __UNUSED__,
@@ -85,12 +145,72 @@ _elm_plug_smart_add(Evas_Object *obj)
    _sizing_eval(obj);
 }
 
+static Ecore_Evas*
+_elm_plug_ecore_evas_get(Evas_Object *obj)
+{
+   Ecore_Evas *ee = NULL;
+   Evas_Object *plug_img = NULL;
+
+   ELM_PLUG_CHECK(obj) NULL;
+
+   plug_img = elm_plug_image_object_get(obj);
+   if (!plug_img) return NULL;
+
+   ee = ecore_evas_object_ecore_evas_get(plug_img);
+   return ee;
+}
+
+static Eina_Bool
+_elm_plug_smart_activate(Evas_Object *obj, Elm_Activate act)
+{
+   Ecore_Evas *ee = NULL;
+   Elm_Access_Action_Info *action_info = NULL;
+   int msg_id = ELM_ACCESS_ACTION_FIRST;
+
+   if (act != ELM_ACTIVATE_DEFAULT &&
+       act != ELM_ACTIVATE_UP &&
+       act != ELM_ACTIVATE_DOWN) return EINA_FALSE;
+
+   ee = _elm_plug_ecore_evas_get(obj);
+   if (!ee) return EINA_FALSE;
+
+   switch (act)
+     {
+       case ELM_ACTIVATE_DEFAULT:
+          msg_id = ELM_ACCESS_ACTION_ACTIVATE;
+          break;
+
+       case ELM_ACTIVATE_UP:
+          msg_id = ELM_ACCESS_ACTION_UP;
+          break;
+
+       case ELM_ACTIVATE_DOWN:
+          msg_id = ELM_ACCESS_ACTION_DOWN;
+          break;
+
+       default:
+          break;
+     }
+
+   if (msg_id == ELM_ACCESS_ACTION_FIRST) return EINA_FALSE;
+
+   action_info = calloc(1, sizeof(Elm_Access_Action_Info));
+   action_info->action_type = msg_id;
+
+   ecore_evas_msg_parent_send(ee, MSG_DOMAIN_CONTROL_ACCESS,
+                              msg_id, &action_info, sizeof(Elm_Access_Action_Info));
+
+   free(action_info);
+   return EINA_TRUE;
+}
+
 static void
 _elm_plug_smart_set_user(Elm_Plug_Smart_Class *sc)
 {
    ELM_WIDGET_CLASS(sc)->base.add = _elm_plug_smart_add;
 
    ELM_WIDGET_CLASS(sc)->theme = _elm_plug_smart_theme;
+   ELM_WIDGET_CLASS(sc)->activate = _elm_plug_smart_activate;
 }
 
 EAPI const Elm_Plug_Smart_Class *
@@ -108,6 +228,41 @@ elm_plug_smart_class_get(void)
    return class;
 }
 
+static Eina_Bool
+_access_action_highlight_next_cb(void *data __UNUSED__,
+                                 Evas_Object *obj,
+                                 void *action_info)
+{
+   Ecore_Evas *ee = NULL;
+   Elm_Access_Action_Info *ai = action_info;
+
+   ee = _elm_plug_ecore_evas_get(obj);
+   if (!ee) return EINA_TRUE;
+
+   ecore_evas_msg_parent_send(ee, MSG_DOMAIN_CONTROL_ACCESS,
+                              ai->action_type,
+                              ai, sizeof(Elm_Access_Action_Info));
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_access_action_highlight_cb(void *data __UNUSED__,
+                            Evas_Object *obj, void *action_info)
+{
+   Ecore_Evas *ee = NULL;
+
+   ee = _elm_plug_ecore_evas_get(obj);
+   if (!ee) return EINA_FALSE;
+
+   elm_access_action_cb_set(obj, ELM_ACCESS_ACTION_HIGHLIGHT_NEXT,
+                            _access_action_highlight_next_cb, NULL);
+
+   ecore_evas_msg_parent_send(ee, MSG_DOMAIN_CONTROL_ACCESS,
+                              ELM_ACCESS_ACTION_HIGHLIGHT,
+                              action_info, sizeof(Elm_Access_Action_Info));
+   return EINA_FALSE;
+}
+
 EAPI Evas_Object *
 elm_plug_add(Evas_Object *parent)
 {
@@ -124,6 +279,10 @@ elm_plug_add(Evas_Object *parent)
    if (!elm_widget_sub_object_add(parent, obj))
      ERR("could not add %p as sub object of %p", obj, parent);
 
+   _elm_access_object_register(obj, ELM_WIDGET_DATA(sd)->resize_obj);
+   elm_access_action_cb_set(obj, ELM_ACCESS_ACTION_HIGHLIGHT,
+                            _access_action_highlight_cb, NULL);
+
    return obj;
 }
 
@@ -157,8 +316,29 @@ elm_plug_connect(Evas_Object *obj,
 
         ecore_evas_data_set(ee, PLUG_KEY, obj);
         ecore_evas_callback_delete_request_set(ee, _elm_plug_disconnected);
+        ecore_evas_callback_msg_handle_set(ee, _elm_plug_ecore_evas_msg_handle);
         return EINA_TRUE;
      }
    else
      return EINA_FALSE;
 }
+
+EAPI Eina_Bool
+elm_plug_msg_send(Evas_Object *obj,
+                  int msg_domain,
+                  int msg_id,
+                  void *data, int size)
+{
+   Ecore_Evas *ee = NULL;
+   Evas_Object *plug_img = NULL;
+
+   ELM_PLUG_CHECK(obj) EINA_FALSE;
+
+   plug_img = elm_plug_image_object_get(obj);
+   if (!plug_img) return EINA_FALSE;
+
+   ee = ecore_evas_object_ecore_evas_get(plug_img);
+   if (!ee) return EINA_FALSE;
+   ecore_evas_msg_parent_send(ee, msg_domain, msg_id, data, size);
+   return EINA_TRUE;
+}
index 4e91e06..31f95c7 100644 (file)
  */
 
 /**
+ * @typedef Elm_Plug_Message
+ *
+ * Structure holding the message
+ * which elm plug received from ecore evas
+ *
+ */
+struct _Elm_Plug_Message
+{
+   int msg_domain;
+   int msg_id;
+   void *data;
+   int size;
+};
+
+typedef struct _Elm_Plug_Message Elm_Plug_Message;
+
+/**
  * Add a new plug image to the parent.
  *
  * @param parent The parent object
@@ -56,5 +73,20 @@ EAPI Eina_Bool       elm_plug_connect(Evas_Object *obj, const char *svcname, int
 EAPI Evas_Object    *elm_plug_image_object_get(const Evas_Object *obj);
 
 /**
+ * Send message to plug widget's socket
+ *
+ * @param obj The plug object to send message
+ * @param msg_domain The domain of message
+ * @param msg_id The id of message
+ * @param data The data of message
+ * @param size The size of message data
+ *
+ * @warning Support for this depends on the underlying windowing system.
+ * @since 1.8.0
+ *
+ */
+EAPI Eina_Bool       elm_plug_msg_send(Evas_Object *obj, int msg_domain, int msg_id, void *data, int size); 
+
+/**
  * @}
  */