[accessability] Initial merge
authorraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Fri, 19 Aug 2011 11:07:42 +0000 (11:07 +0000)
committerMike McCormack <mj.mccormack@samsung.com>
Mon, 14 Nov 2011 07:44:21 +0000 (16:44 +0900)
this is... the beginning of accessibility supportin elm. it's direct
as in elm manages it itself - all it needs is a module to send text
to. one is provided here that just execs espeak and handles a stream
of things for it to say. this is only a start and is still being
fleshed out.

git-svn-id: https://svn.enlightenment.org/svn/e/trunk/elementary@62585 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

configure.ac
data/themes/widgets/label.edc [new file with mode: 0644]
src/lib/Makefile.am
src/lib/elm_access.c [new file with mode: 0644]
src/lib/elm_button.c
src/lib/elm_widget.h
src/modules/Makefile.am
src/modules/access_output/mod.c

index 827c2fe..363ec94 100755 (executable)
@@ -643,6 +643,7 @@ src/lib/Makefile
 src/lib/Elementary.h
 src/bin/Makefile
 src/modules/Makefile
+src/modules/access_output/Makefile
 src/modules/test_entry/Makefile
 src/modules/test_map/Makefile
 src/modules/ctxpopup_copypasteUI/Makefile
diff --git a/data/themes/widgets/label.edc b/data/themes/widgets/label.edc
new file mode 100644 (file)
index 0000000..cc190a8
--- /dev/null
@@ -0,0 +1,466 @@
+#define TEXT_SLIDE_DURATION     10
+
+group { name: "elm/label/base/default";
+   data.item: "default_font_size" "10";
+   data.item: "min_font_size" "6";
+   data.item: "max_font_size" "60";
+   styles {
+      style { name: "textblock_style";
+         base: "font=Sans font_size=10 color=#000 text_class=label";
+         tag:  "br" "\n";
+         tag:  "ps" "ps";
+         tag:  "hilight" "+ font_weight=Bold";
+         tag:  "b" "+ font_weight=Bold";
+         tag:  "tab" "\t";
+      }
+   }
+   parts {
+      part { name: "label.swallow.background";
+         type: SWALLOW;
+         description { state: "default" 0.0;
+            visible: 1;
+         }
+      }
+      part { name: "label.text.clip";
+         type: RECT;
+         description { state: "default" 0.0;
+            rel1 { relative: 0 0; to: "label.swallow.background"; }
+            rel2 { relative: 1 1; to: "label.swallow.background"; }
+         }
+      }
+      part { name: "elm.text";
+         type: TEXTBLOCK;
+         scale: 1;
+         clip_to: "label.text.clip";
+         description { state: "default" 0.0;
+            rel1.relative: 0.0 0.0;
+            rel2.relative: 1.0 1.0;
+            text {
+               style: "textblock_style";
+               min: 0 1;
+            }
+         }
+      }
+   }
+}
+
+group { name: "elm/label/base/marker";
+   data.item: "default_font_size" "10";
+   data.item: "min_font_size" "6";
+   data.item: "max_font_size" "60";
+   styles {
+      style { name: "textblock_style2";
+         base: "font=Sans:style=Bold font_size=10 align=center color=#fff wrap=word text_class=label";
+         tag:  "br" "\n";
+         tag:  "ps" "ps";
+         tag:  "hilight" "+ color=#ffff";
+         tag:  "b" "+ color=#ffff";
+         tag:  "tab" "\t";
+      }
+   }
+   parts {
+      part { name: "label.swallow.background";
+         type: SWALLOW;
+         description { state: "default" 0.0;
+            visible: 1;
+            rel1 { relative: 0 0; to: "elm.text"; }
+            rel2 { relative: 1 1; to: "elm.text"; }
+         }
+      }
+      part { name: "elm.text";
+         type: TEXTBLOCK;
+         scale: 1;
+         description { state: "default" 0.0;
+            text {
+               style: "textblock_style2";
+               min: 1 1;
+            }
+         }
+      }
+   }
+}
+
+group { name: "elm/label/base/slide_long";
+   data.item: "default_font_size" "10";
+   data.item: "min_font_size" "6";
+   data.item: "max_font_size" "60";
+
+   script {
+      public g_duration, g_stopslide, g_timer_id, g_anim_id;
+
+      public message(Msg_Type:type, id, ...) {
+         if ((type == MSG_FLOAT_SET) && (id == 0)) {
+            new Float:duration;
+            duration = getfarg(2);
+            set_float(g_duration, duration);
+         }
+      }
+      public slide_to_end_anim(val, Float:pos) {
+         new stopflag;
+         new id;
+         stopflag = get_int(g_stopslide);
+         if (stopflag == 1) return;
+         set_tween_state(PART:"elm.text", pos, "slide_begin", 0.0, "slide_end", 0.0);
+         if (pos >= 1.0) {
+            id = timer(0.5, "slide_to_begin", 1);
+            set_int(g_timer_id, id);
+         }
+      }
+      public slide_to_end() {
+         new stopflag;
+         new id;
+         new Float:duration;
+         stopflag = get_int(g_stopslide);
+         if (stopflag == 1) return;
+         duration = get_float(g_duration);
+         id = anim(duration, "slide_to_end_anim", 1);
+         set_int(g_anim_id, id);
+      }
+      public slide_to_begin() {
+         new stopflag;
+         new id;
+         stopflag = get_int(g_stopslide);
+         if (stopflag == 1) return;
+         set_state(PART:"elm.text", "slide_begin", 0.0);
+         id = timer(0.5, "slide_to_end", 1);
+         set_int(g_timer_id, id);
+      }
+      public start_slide() {
+         set_int(g_stopslide, 0);
+         set_state(PART:"elm.text", "slide_begin", 0.0);
+         slide_to_end();
+      }
+      public stop_slide() {
+         new id;
+         set_int(g_stopslide, 1);
+         id = get_int(g_anim_id);
+         cancel_anim(id);
+         id = get_int(g_timer_id);
+         cancel_timer(id);
+         set_state(PART:"elm.text", "default", 0.0);
+      }
+   }
+
+   parts {
+      part { name: "label.swallow.background";
+         type: SWALLOW;
+         description { state: "default" 0.0;
+            visible: 1;
+         }
+      }
+      part { name: "label.text.clip";
+         type: RECT;
+         description { state: "default" 0.0;
+            visible: 1;
+            color: 255 255 255 255;
+            rel1 { relative: 0 0; to: "label.swallow.background"; }
+            rel2 { relative: 1 1; to: "label.swallow.background"; }
+         }
+      }
+      part { name: "elm.text";
+         type: TEXTBLOCK;
+         scale: 1;
+         clip_to: "label.text.clip";
+         description { state: "default" 0.0;
+            rel1.relative: 0.0 0.0;
+            rel2.relative: 1.0 1.0;
+            align: 0.0 0.0;
+            text {
+               style: "textblock_style";
+               min: 1 1;
+            }
+         }
+         description { state: "slide_end" 0.0;
+            inherit: "default" 0.0;
+            rel1.relative: 0.0 0.0;
+            rel2.relative: 0.0 1.0;
+            align: 1.0 0.0;
+         }
+         description { state: "slide_begin" 0.0;
+            inherit: "default" 0.0;
+            rel1.relative: 1.0 0.0;
+            rel2.relative: 1.0 1.0;
+            align: 0.0 0.0;
+         }
+      }
+   }
+   programs {
+      program { name: "start_slide";
+         source: "elm";
+         signal: "elm,state,slide,start";
+         script
+         {
+            start_slide();
+         }
+      }
+      program { name: "stop_slide";
+         source: "elm";
+         signal: "elm,state,slide,stop";
+         script
+         {
+            stop_slide();
+         }
+      }
+   }
+}
+
+
+group { name: "elm/label/base/slide_short";
+   data.item: "default_font_size" "10";
+   data.item: "min_font_size" "6";
+   data.item: "max_font_size" "60";
+
+   script {
+      public g_duration, g_stopslide, g_timer_id, g_anim_id;
+
+      public message(Msg_Type:type, id, ...) {
+         if ((type == MSG_FLOAT_SET) && (id == 0)) {
+            new Float:duration;
+            duration = getfarg(2);
+            set_float(g_duration, duration);
+         }
+      }
+      public slide_to_end_anim(val, Float:pos) {
+         new stopflag;
+         new id;
+         stopflag = get_int(g_stopslide);
+         if (stopflag == 1) return;
+         set_tween_state(PART:"elm.text", pos, "slide_begin", 0.0, "slide_end", 0.0);
+         if (pos >= 1.0) {
+            id = timer(0.5, "slide_to_begin", 1);
+            set_int(g_timer_id, id);
+         }
+      }
+      public slide_to_end() {
+         new stopflag;
+         new id;
+         new Float:duration;
+         stopflag = get_int(g_stopslide);
+         if (stopflag == 1) return;
+         duration = get_float(g_duration);
+         id = anim(duration, "slide_to_end_anim", 1);
+         set_int(g_anim_id, id);
+      }
+      public slide_to_begin() {
+         new stopflag;
+         new id;
+         stopflag = get_int(g_stopslide);
+         if (stopflag == 1) return;
+         set_state(PART:"elm.text", "slide_begin", 0.0);
+         id = timer(0.5, "slide_to_end", 1);
+         set_int(g_timer_id, id);
+      }
+      public start_slide() {
+         set_int(g_stopslide, 0);
+         set_state(PART:"elm.text", "slide_begin", 0.0);
+         slide_to_end();
+      }
+      public stop_slide() {
+         new id;
+         set_int(g_stopslide, 1);
+         id = get_int(g_anim_id);
+         cancel_anim(id);
+         id = get_int(g_timer_id);
+         cancel_timer(id);
+         set_state(PART:"elm.text", "default", 0.0);
+      }
+   }
+
+   parts {
+      part { name: "label.swallow.background";
+         type: SWALLOW;
+         description { state: "default" 0.0;
+            visible: 1;
+         }
+      }
+      part { name: "label.text.clip";
+         type: RECT;
+         description { state: "default" 0.0;
+            visible: 1;
+            color: 255 255 255 255;
+            rel1 { relative: 0 0; to: "label.swallow.background"; }
+            rel2 { relative: 1 1; to: "label.swallow.background"; }
+         }
+      }
+      part { name: "elm.text";
+         type: TEXTBLOCK;
+         scale: 1;
+         clip_to: "label.text.clip";
+         description { state: "default" 0.0;
+            rel1.relative: 0.0 0.0;
+            rel2.relative: 1.0 1.0;
+            align: 0.0 0.0;
+            text {
+               style: "textblock_style";
+               min: 1 1;
+            }
+         }
+         description { state: "slide_end" 0.0;
+            inherit: "default" 0.0;
+            rel1.relative: 1.0 0.0;
+            rel2.relative: 1.0 1.0;
+            align: 1.0 0.0;
+         }
+         description { state: "slide_begin" 0.0;
+            inherit: "default" 0.0;
+            rel1.relative: 0.0 0.0;
+            rel2.relative: 0.0 1.0;
+            align: 0.0 0.0;
+         }
+      }
+   }
+   programs {
+      program { name: "start_slide";
+         source: "elm";
+         signal: "elm,state,slide,start";
+         script
+         {
+            start_slide();
+         }
+      }
+      program { name: "stop_slide";
+         source: "elm";
+         signal: "elm,state,slide,stop";
+         script
+         {
+            stop_slide();
+         }
+      }
+   }
+}
+
+group { name: "elm/label/base/slide_bounce";
+   data.item: "default_font_size" "10";
+   data.item: "min_font_size" "6";
+   data.item: "max_font_size" "60";
+
+   script {
+      public g_duration, g_stopslide, g_timer_id, g_anim_id;
+
+      public message(Msg_Type:type, id, ...) {
+         if ((type == MSG_FLOAT_SET) && (id == 0)) {
+            new Float:duration;
+            duration = getfarg(2);
+            set_float(g_duration, duration);
+         }
+      }
+      public slide_to_end_anim(val, Float:pos) {
+         new stopflag;
+         new id;
+         stopflag = get_int(g_stopslide);
+         if (stopflag == 1) return;
+         set_tween_state(PART:"elm.text", pos, "slide_begin", 0.0, "slide_end", 0.0);
+         if (pos >= 1.0) {
+            id = timer(0.5, "slide_to_begin", 1);
+            set_int(g_timer_id, id);
+         }
+      }
+      public slide_to_end() {
+         new stopflag;
+         new id;
+         new Float:duration;
+         stopflag = get_int(g_stopslide);
+         if (stopflag == 1) return;
+         duration = get_float(g_duration);
+         id = anim(duration, "slide_to_end_anim", 1);
+         set_int(g_anim_id, id);
+      }
+      public slide_to_begin_anim(val, Float:pos) {
+         new stopflag;
+         new id;
+         stopflag = get_int(g_stopslide);
+         if (stopflag == 1) return;
+         set_tween_state(PART:"elm.text", pos, "slide_end", 0.0, "slide_begin", 0.0);
+         if (pos >= 1.0) {
+            id = timer(0.5, "slide_to_end", 1);
+            set_int(g_timer_id, id);
+         }
+      }
+      public slide_to_begin() {
+         new stopflag;
+         new id;
+         new Float:duration;
+         stopflag = get_int(g_stopslide);
+         if (stopflag == 1) return;
+         duration = get_float(g_duration);
+         id = anim(duration, "slide_to_begin_anim", 1);
+         set_int(g_anim_id, id);
+      }
+      public start_slide() {
+         set_int(g_stopslide, 0);
+         set_state(PART:"elm.text", "slide_begin", 0.0);
+         slide_to_end();
+      }
+      public stop_slide() {
+         new id;
+         set_int(g_stopslide, 1);
+         id = get_int(g_anim_id);
+         cancel_anim(id);
+         id = get_int(g_timer_id);
+         cancel_timer(id);
+         set_state(PART:"elm.text", "default", 0.0);
+      }
+   }
+
+   parts {
+      part { name: "label.swallow.background";
+         type: SWALLOW;
+         description { state: "default" 0.0;
+            visible: 1;
+         }
+      }
+      part { name: "label.text.clip";
+         type: RECT;
+         description { state: "default" 0.0;
+            visible: 1;
+            color: 255 255 255 255;
+            rel1 { relative: 0 0; to: "label.swallow.background"; }
+            rel2 { relative: 1 1; to: "label.swallow.background"; }
+         }
+      }
+      part { name: "elm.text";
+         type: TEXTBLOCK;
+         scale: 1;
+         clip_to: "label.text.clip";
+         description { state: "default" 0.0;
+            rel1.relative: 0.0 0.0;
+            rel2.relative: 1.0 1.0;
+            align: 0.0 0.0;
+            text {
+               style: "textblock_style";
+               min: 1 1;
+            }
+         }
+         description { state: "slide_end" 0.0;
+            inherit: "default" 0.0;
+            rel1.relative: 1.0 0.0;
+            rel2.relative: 1.0 1.0;
+            align: 1.0 0.0;
+         }
+         description { state: "slide_begin" 0.0;
+            inherit: "default" 0.0;
+            rel1.relative: 0.0 0.0;
+            rel2.relative: 0.0 1.0;
+            align: 0.0 0.0;
+         }
+      }
+   }
+   programs {
+      program { name: "start_slide";
+         source: "elm";
+         signal: "elm,state,slide,start";
+         script
+         {
+            start_slide();
+         }
+      }
+      program { name: "stop_slide";
+         source: "elm";
+         signal: "elm,state,slide,stop";
+         script
+         {
+            stop_slide();
+         }
+      }
+   }
+}
index ee0c915..800d50a 100644 (file)
@@ -55,6 +55,7 @@ elc_navigationbar.c \
 elc_navigationbar_ex.c\
 elc_player.c \
 elc_scrolled_entry.c \
+elm_access.c \
 elm_actionslider.c \
 elm_bg.c \
 elm_box.c \
diff --git a/src/lib/elm_access.c b/src/lib/elm_access.c
new file mode 100644 (file)
index 0000000..d441d63
--- /dev/null
@@ -0,0 +1,245 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+typedef struct _Mod_Api Mod_Api;
+
+struct _Mod_Api
+{
+   void (*out_read) (const char *txt);
+   void (*out_read_done) (void);
+   void (*out_cancel) (void);
+   void (*out_done_callback_set) (void (*func) (void *data), const void *data);
+};
+
+static int initted = 0;
+static Elm_Module *mod = NULL;
+static Mod_Api *mapi = NULL;
+
+static void
+_access_init(void)
+{
+   Elm_Module *m;
+   initted++;
+   if (initted > 1) return;
+   if (!(m = _elm_module_find_as("access/api"))) return;
+   mod = m;
+   m->api = malloc(sizeof(Mod_Api));
+   if (!m->api) return;
+   m->init_func(m);
+   ((Mod_Api *)(m->api)      )->out_read = // called to read out some text
+      _elm_module_symbol_get(m, "out_read");
+   ((Mod_Api *)(m->api)      )->out_read_done = // called to set a done marker so when it is reached the done callback is called
+      _elm_module_symbol_get(m, "out_read_done");
+   ((Mod_Api *)(m->api)      )->out_cancel = // called to read out some text
+      _elm_module_symbol_get(m, "out_cancel");
+   ((Mod_Api *)(m->api)      )->out_done_callback_set = // called when last read done
+      _elm_module_symbol_get(m, "out_done_callback_set");
+   mapi = m->api;
+}
+
+static Elm_Access_Item *
+_access_add_set(Elm_Access_Info *ac, int type)
+{
+   Elm_Access_Item *ai;
+   Eina_List *l;
+
+   if (!ac) return NULL;
+   EINA_LIST_FOREACH(ac->items, l, ai)
+     {
+        if (ai->type == type)
+          {
+             if (!ai->func)
+               {
+                  if (ai->data) eina_stringshare_del(ai->data);
+               }
+             ai->func = NULL;
+             ai->data = NULL;
+             return ai;
+          }
+     }
+   ai = calloc(1, sizeof(Elm_Access_Item));
+   ai->type = type;
+   ac->items = eina_list_prepend(ac->items, ai);
+   return ai;
+}
+static Eina_Bool
+_access_obj_over_timeout_cb(void *data)
+{
+   Elm_Access_Info *ac = evas_object_data_get(data, "_elm_access");
+   if (!ac) return EINA_FALSE;
+   _elm_access_read(ac, ELM_ACCESS_CANCEL, data, NULL);
+   _elm_access_read(ac, ELM_ACCESS_TYPE,   data, NULL);
+   _elm_access_read(ac, ELM_ACCESS_INFO,   data, NULL);
+   _elm_access_read(ac, ELM_ACCESS_STATE,  data, NULL);
+   _elm_access_read(ac, ELM_ACCESS_DONE,   data, NULL);
+   ac->delay_timer = NULL;
+   return EINA_FALSE;
+}
+
+static void
+_access_obj_mouse_in_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info  __UNUSED__)
+{
+   Elm_Access_Info *ac = evas_object_data_get(data, "_elm_access");
+   if (!ac) return;
+
+   if (ac->delay_timer)
+     {
+        ecore_timer_del(ac->delay_timer);
+        ac->delay_timer = NULL;
+     }
+   ac->delay_timer = ecore_timer_add(0.2, _access_obj_over_timeout_cb, data);
+}
+
+static void
+_access_obj_mouse_out_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Elm_Access_Info *ac = evas_object_data_get(data, "_elm_access");
+   if (!ac) return;
+   if (ac->delay_timer)
+     {
+        ecore_timer_del(ac->delay_timer);
+        ac->delay_timer = NULL;
+     }
+}
+
+static void
+_access_obj_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Elm_Access_Info *ac;
+   
+   evas_object_event_callback_del_full(obj, EVAS_CALLBACK_MOUSE_IN,
+                                       _access_obj_mouse_in_cb, data);
+   evas_object_event_callback_del_full(obj, EVAS_CALLBACK_MOUSE_OUT,
+                                       _access_obj_mouse_out_cb, data);
+   evas_object_event_callback_del_full(obj, EVAS_CALLBACK_DEL,
+                                       _access_obj_del_cb, data);
+   ac = evas_object_data_get(data, "_elm_access");
+   evas_object_data_del(data, "_elm_access");
+   if (ac)
+     {
+        _elm_access_clear(ac);
+        free(ac);
+     }
+}
+
+static void
+_access_read_done(void *data __UNUSED__)
+{
+   printf("read done\n");
+}
+
+//-------------------------------------------------------------------------//
+
+EAPI void
+_elm_access_clear(Elm_Access_Info *ac)
+{
+   Elm_Access_Item *ai;
+
+   if (!ac) return;
+   if (ac->delay_timer)
+     {
+        ecore_timer_del(ac->delay_timer);
+        ac->delay_timer = NULL;
+     }
+   EINA_LIST_FREE(ac->items, ai)
+     {
+        if (!ai->func)
+          {
+             if (ai->data) eina_stringshare_del(ai->data);
+          }
+        free(ai);
+     }
+}
+
+EAPI void
+_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->data = eina_stringshare_add(text);
+}
+
+EAPI void
+_elm_access_callback_set(Elm_Access_Info *ac, int type, Elm_Access_Content_Cb func, const void *data)
+{
+   Elm_Access_Item *ai = _access_add_set(ac, type);
+   if (!ai) return;
+   ai->func = func;
+   ai->data = data;
+}
+
+EAPI char *
+_elm_access_text_get(Elm_Access_Info *ac, int type, Evas_Object *obj, Elm_Widget_Item *item)
+{
+   Elm_Access_Item *ai;
+   Eina_List *l;
+   
+   if (!ac) return NULL;
+   EINA_LIST_FOREACH(ac->items, l, ai)
+     {
+        if (ai->type == type)
+          {
+             if (ai->func) return ai->func(ai->data, obj, item);
+             else if (ai->data) return strdup(ai->data);
+             return NULL;
+          }
+     }
+   return NULL;
+}
+
+EAPI void
+_elm_access_read(Elm_Access_Info *ac, int type, Evas_Object *obj, Elm_Widget_Item *item)
+{
+   char *txt = _elm_access_text_get(ac, type, obj, item);
+
+   _access_init();
+   if (mapi)
+     {
+        if (mapi->out_done_callback_set)
+           mapi->out_done_callback_set(_access_read_done, NULL);
+        if (type == ELM_ACCESS_DONE)
+          {
+             if (mapi->out_read_done) mapi->out_read_done();
+          }
+        else if (type == ELM_ACCESS_CANCEL)
+          {
+             if (mapi->out_cancel) mapi->out_cancel();
+          }
+        else
+          {
+             if (txt)
+               {
+                  if (mapi->out_read) mapi->out_read(txt);
+                  if (mapi->out_read) mapi->out_read(".\n");
+               }
+          }
+     }
+   if (txt) free(txt);
+}
+
+EAPI Elm_Access_Info *
+_elm_access_object_get(Evas_Object *obj)
+{
+   return evas_object_data_get(obj, "_elm_access");
+}
+
+EAPI void
+_elm_access_object_register(Evas_Object *obj, Evas_Object *hoverobj)
+{
+   Elm_Access_Info *ac;
+   
+   evas_object_event_callback_add(hoverobj, EVAS_CALLBACK_MOUSE_IN,
+                                  _access_obj_mouse_in_cb, obj);
+   evas_object_event_callback_add(hoverobj, EVAS_CALLBACK_MOUSE_OUT,
+                                  _access_obj_mouse_out_cb, obj);
+   evas_object_event_callback_add(hoverobj, EVAS_CALLBACK_DEL,
+                                  _access_obj_del_cb, obj);
+   ac = calloc(1, sizeof(Elm_Access_Info));
+   evas_object_data_set(obj, "_elm_access", ac);
+}
+
+// XXX special version for items
+//EAPI void
+//_elm_access_item_hover_register(Elm_Widget_Item *item, Evas_Object *hoverobj)
+//{
+//}
index aa40546..7f784ea 100644 (file)
@@ -425,6 +425,14 @@ _elm_button_label_get(const Evas_Object *obj, const char *item)
    return wd->label;
 }
 
+static char *
+_access_info_cb(const void *data, Evas_Object *obj, Elm_Widget_Item *item)
+{
+   const char *txt = _elm_button_label_get(obj, NULL);
+   if (txt) return strdup(txt);
+   return txt;
+}
+
 EAPI Evas_Object *
 elm_button_add(Evas_Object *parent)
 {
@@ -482,6 +490,12 @@ elm_button_add(Evas_Object *parent)
    // TODO: convert Elementary to subclassing of Evas_Smart_Class
    // TODO: and save some bytes, making descriptions per-class and not instance!
    evas_object_smart_callbacks_descriptions_set(obj, _signals);
+   
+   _elm_access_object_register(obj, wd->btn);
+   _elm_access_text_set(_elm_access_object_get(obj),
+                        ELM_ACCESS_TYPE, E_("Button"));
+   _elm_access_callback_set(_elm_access_object_get(obj),
+                            ELM_ACCESS_INFO, _access_info_cb, obj);
    return obj;
 }
 
index a6d6930..f8690c9 100644 (file)
@@ -192,6 +192,9 @@ typedef struct _Elm_Tooltip Elm_Tooltip;
 typedef struct _Elm_Cursor Elm_Cursor;
 typedef struct _Elm_Widget_Item Elm_Widget_Item; /**< base structure for all widget items that are not Elm_Widget themselves */
 
+typedef struct _Elm_Access_Info Elm_Access_Info; /**< accessibility information to be able to set and get from the access API */
+typedef struct _Elm_Access_Item Elm_Access_Item; /**< accessibility info item */
+
 typedef void (*Elm_Widget_On_Text_Set_Cb)(void *data, const char *part, const char *text);
 typedef void (*Elm_Widget_On_Content_Set_Cb)(void *data, const char *part, Evas_Object *content);
 typedef const char *(*Elm_Widget_On_Text_Get_Cb)(const void *data, const char *part);
@@ -199,6 +202,37 @@ typedef Evas_Object *(*Elm_Widget_On_Content_Get_Cb)(const void *data, const cha
 typedef Evas_Object *(*Elm_Widget_On_Content_Unset_Cb)(const void *data, const char *part);
 typedef void (*Elm_Widget_On_Signal_Emit_Cb)(void *data, const char *emission, const char *source);
 
+#define ELM_ACCESS_TYPE     0 // when reading out widget or item this is read first
+#define ELM_ACCESS_INFO     1 // next read is info - this is normally label
+#define ELM_ACCESS_STATE    2 // if there is a state (eg checkbox) then read state out
+#define ELM_ACCESS_CONTENT  3 // read ful content - eg all of the label, not a shortened version
+
+#define ELM_ACCESS_DONE    -1 // sentence done - send done event here
+#define ELM_ACCESS_CANCEL  -2 // stop reading immediately
+
+typedef char *(*Elm_Access_Content_Cb)(const void *data, Evas_Object *obj, Elm_Widget_Item *item);
+
+struct _Elm_Access_Item
+{
+   int type;
+   const void *data;
+   Elm_Access_Content_Cb func;
+};
+
+struct _Elm_Access_Info
+{
+   Eina_List *items;
+   Ecore_Timer *delay_timer;
+};
+
+EAPI void             _elm_access_clear(Elm_Access_Info *ac);
+EAPI void             _elm_access_text_set(Elm_Access_Info *ac, int type, const char *text);
+EAPI void             _elm_access_callback_set(Elm_Access_Info *ac, int type, Elm_Access_Content_Cb func, const void *data);
+EAPI char            *_elm_access_text_get(Elm_Access_Info *ac, int type,  Evas_Object *obj, Elm_Widget_Item *item);
+EAPI void             _elm_access_read(Elm_Access_Info *ac, int type, Evas_Object *obj, Elm_Widget_Item *item);
+EAPI Elm_Access_Info *_elm_access_object_get(Evas_Object *obj);
+EAPI void             _elm_access_object_register(Evas_Object *obj, Evas_Object *hoverobj);
+
 #define ELM_WIDGET_ITEM Elm_Widget_Item base /**< put this as the first member in your widget item struct */
 struct _Elm_Widget_Item
 {
index 580ce2d..11a6ca7 100755 (executable)
@@ -6,4 +6,5 @@ test_entry \
 ctxpopup_copypasteUI \
 ctxpopup_copypasteshareUI \
 popup_copypasteUI \
-test_map
+test_map \
+access_output
index 3956a40..5dbe3a6 100644 (file)
@@ -39,7 +39,7 @@ _exe_del(void *data __UNUSED__, int type __UNUSED__, void *event)
 EAPI int
 elm_modapi_init(void *m __UNUSED__)
 {
-   exe_exit_handler =
+   exe_exit_handler = 
       ecore_event_handler_add(ECORE_EXE_EVENT_DEL,
                               _exe_del, NULL);
    return 1; // succeed always