#include <Elementary.h>
#include "elm_priv.h"
+#include "elm_interface_scrollable.h"
static const char ACCESS_SMART_NAME[] = "elm_access";
(ACCESS_SMART_NAME, _elm_access, Elm_Widget_Smart_Class,
Elm_Widget_Smart_Class, elm_widget_smart_class_get, NULL);
+struct _Func_Data
+{
+ void *user_data; /* Holds user data to CB */
+ Elm_Access_Action_Cb cb;
+};
+
+typedef struct _Func_Data Func_Data;
+
+struct _Action_Info
+{
+ Evas_Object *obj;
+ Func_Data fn[ELM_ACCESS_ACTION_LAST + 1]; /* Callback for specific action */
+};
+
+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);
static Eina_Bool
_elm_access_smart_activate(Evas_Object *obj, Elm_Activate act)
{
+ int type = ELM_ACCESS_ACTION_FIRST;
+
+ Action_Info *a;
+ a = evas_object_data_get(obj, "_elm_access_action_info");
+
+ switch (act)
+ {
+ case ELM_ACTIVATE_DEFAULT:
+ type = ELM_ACCESS_ACTION_ACTIVATE;
+ break;
+
+ case ELM_ACTIVATE_UP:
+ type = ELM_ACCESS_ACTION_VALUE_CHANGE;
+ break;
+
+ case ELM_ACTIVATE_DOWN:
+ type = ELM_ACCESS_ACTION_VALUE_CHANGE;
+ break;
+
+ case ELM_ACTIVATE_RIGHT:
+ break;
+
+ case ELM_ACTIVATE_LEFT:
+ break;
+
+ case ELM_ACTIVATE_BACK:
+ type = ELM_ACCESS_ACTION_BACK;
+ break;
+
+ default:
+ break;
+ }
+
+ if ((a) && (type > ELM_ACCESS_ACTION_FIRST) &&
+ (type < ELM_ACCESS_ACTION_LAST) &&
+ (a->fn[type].cb))
+ {
+ a->fn[type].cb(a->fn[type].user_data, obj, NULL);
+ return EINA_TRUE;
+ }
+
+ /* TODO: deprecate below? and change above with _access_action_callback_call(); */
if (act != ELM_ACTIVATE_DEFAULT) return EINA_FALSE;
Elm_Access_Info *ac = evas_object_data_get(obj, "_elm_access");
return ho;
}
+static void
+_access_highlight_read(Elm_Access_Info *ac, Evas_Object *obj)
+{
+ int type;
+ char *txt = NULL;
+ Eina_Strbuf *strbuf;
+
+ /*FIXME: TIZEN only - read at once because Tizen TTS engine performance is not good */
+ strbuf = eina_strbuf_new();
+
+ if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
+ {
+
+ if (ac->on_highlight) ac->on_highlight(ac->on_highlight_data);
+ _elm_access_object_hilight(obj);
+
+ for (type = ELM_ACCESS_INFO_FIRST + 1; type < ELM_ACCESS_INFO_LAST; type++)
+ {
+ txt = _elm_access_text_get(ac, type, obj);
+ if (txt && (strlen(txt) > 0))
+ {
+ if (eina_strbuf_length_get(strbuf) > 0)
+ eina_strbuf_append_printf(strbuf, ", %s", txt);
+ else
+ eina_strbuf_append(strbuf, txt);
+
+ free(txt);
+ }
+ }
+ }
+
+ txt = eina_strbuf_string_steal(strbuf);
+ eina_strbuf_free(strbuf);
+
+ _elm_access_say(txt);
+ free(txt);
+}
+
static Eina_Bool
_access_obj_over_timeout_cb(void *data)
{
if (!data) return EINA_FALSE;
- ho = _access_highlight_object_get(data);
- if (ho == data) return EINA_FALSE;
-
ac = evas_object_data_get(data, "_elm_access");
if (!ac) return EINA_FALSE;
- if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
- {
- if (ac->on_highlight) ac->on_highlight(ac->on_highlight_data);
- _elm_access_object_hilight(data);
- _elm_access_read(ac, ELM_ACCESS_CANCEL, data);
- _elm_access_read(ac, ELM_ACCESS_INFO, data);
- _elm_access_read(ac, ELM_ACCESS_TYPE, data);
- _elm_access_read(ac, ELM_ACCESS_STATE, data);
- _elm_access_read(ac, ELM_ACCESS_CONTEXT_INFO, data);
- _elm_access_read(ac, ELM_ACCESS_DONE, data);
- }
+ ho = _access_highlight_object_get(data);
+ if (ho != data) _access_highlight_read(ac, data);
+
ac->delay_timer = NULL;
return EINA_FALSE;
}
item->access_order = eina_list_remove_list(item->access_order, l);
}
}
+
+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,
+ void *data)
+{
+ Action_Info *a;
+ Eina_Bool ret;
+
+ ret = EINA_FALSE;
+ a = evas_object_data_get(obj, "_elm_access_action_info");
+
+ if (a && (a->fn[type].cb))
+ ret = a->fn[type].cb(a->fn[type].user_data, obj, data);
+
+ return ret;
+}
+
+static Eina_Bool
+_access_highlight_next_get(Evas_Object *obj, Elm_Focus_Direction dir)
+{
+ int type;
+ Evas_Object *ho, *parent, *target;
+ Eina_Bool ret;
+
+ target = NULL;
+ ret = EINA_FALSE;
+
+ if (!elm_widget_is(obj)) return ret;
+
+ ho = _access_highlight_object_get(obj);
+ if (!ho) return ret;
+
+ parent = ho;
+
+ /* find highlight root */
+ do
+ {
+ ELM_WIDGET_DATA_GET(parent, sd);
+ if (sd->highlight_root)
+ {
+ /* change highlight root */
+ obj = parent;
+ break;
+ }
+ parent = elm_widget_parent_get(parent);
+ }
+ while (parent);
+
+ _elm_access_read_mode_set(EINA_TRUE);
+
+ ret = elm_widget_focus_next_get(obj, dir, &target);
+ if (ret && target)
+ {
+ if (dir == ELM_FOCUS_NEXT)
+ type = ELM_ACCESS_ACTION_HIGHLIGHT_NEXT;
+ else
+ type = ELM_ACCESS_ACTION_HIGHLIGHT_PREV;
+
+ 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;
+ }
+ }
+
+ _elm_access_read_mode_set(EINA_FALSE);
+
+ return ret;
+}
+
//-------------------------------------------------------------------------//
EAPI void
_elm_access_highlight_set(Evas_Object* obj)
{
- _access_obj_over_timeout_cb(obj);
+ Evas *evas;
+ Elm_Access_Info *ac;
+ Evas_Object *ho;
+ Evas_Coord_Point ho_point = { 0, 0 };
+
+ if (!obj) return;
+
+ ho = _access_highlight_object_get(obj);
+ if (ho == obj) return;
+
+ ac = evas_object_data_get(obj, "_elm_access");
+ 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
{
Elm_Access_Item *ai = _access_add_set(ac, type);
if (!ai) return;
+ ai->func = NULL;
ai->data = eina_stringshare_add(text);
}
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;
}
EAPI void
_elm_access_highlight_cycle(Evas_Object *obj, Elm_Focus_Direction dir)
{
- Evas_Object *ho;
+ int type;
+ Evas_Object *ho, *parent;
+
ho = _access_highlight_object_get(obj);
if (!ho) return;
+ parent = ho;
+
/* find highlight root */
do
{
- ELM_WIDGET_DATA_GET(ho, sd);
+ ELM_WIDGET_DATA_GET(parent, sd);
if (sd->highlight_root)
{
/* change highlight root */
- obj = ho;
+ obj = parent;
break;
}
- ho = elm_widget_parent_get(ho);
+ parent = elm_widget_parent_get(parent);
}
- while (ho);
+ while (parent);
_elm_access_read_mode_set(EINA_TRUE);
- elm_widget_focus_cycle(obj, dir);
+
+ if (dir == ELM_FOCUS_NEXT)
+ type = ELM_ACCESS_ACTION_HIGHLIGHT_NEXT;
+ 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);
}
if (txt)
{
if (mapi->out_read) mapi->out_read(txt);
- if (mapi->out_read) mapi->out_read(".\n");
+ //if (mapi->out_read) mapi->out_read(".\n"); /* TIZEN only: Tizen TTS engine performance is not good */
}
if (mapi->out_read_done) mapi->out_read_done();
}
{
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)
_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);
evas_object_geometry_get(obj, &x, &y, &w, &h);
evas_object_move(o, x, y);
evas_object_resize(o, w, h);
- evas_object_show(o);
+
+ /* 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;
+ if (!_access_action_callback_call(obj, ELM_ACCESS_ACTION_HIGHLIGHT, a))
+ evas_object_show(o);
+ else
+ evas_object_hide(o);
+ free(a);
}
EAPI void
_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);
}
}
_elm_access_clear(ac);
free(ac);
}
+
+ Action_Info *a;
+ a = evas_object_data_get(obj, "_elm_access_action_info");
+ if (a) free(a);
}
EAPI void
EAPI void
elm_access_highlight_set(Evas_Object* obj)
{
- _access_obj_over_timeout_cb(obj);
+ _elm_access_highlight_set(obj);
+}
+
+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;
+
+ _elm_access_mouse_event_enabled_set(EINA_TRUE);
+
+ evas_event_feed_mouse_in(evas, 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:
+ if (a->highlight_cycle)
+ _elm_access_highlight_cycle(obj, ELM_FOCUS_NEXT);
+ else
+ return _access_highlight_next_get(obj, ELM_FOCUS_NEXT);
+ break;
+
+ case ELM_ACCESS_ACTION_HIGHLIGHT_PREV:
+ if (a->highlight_cycle)
+ _elm_access_highlight_cycle(obj, ELM_FOCUS_PREVIOUS);
+ else
+ return _access_highlight_next_get(obj, ELM_FOCUS_PREVIOUS);
+ break;
+
+ case ELM_ACCESS_ACTION_ACTIVATE:
+ _elm_access_highlight_object_activate(obj, ELM_ACTIVATE_DEFAULT);
+ break;
+
+ case ELM_ACCESS_ACTION_VALUE_CHANGE:
+ _elm_access_highlight_object_activate(obj, ELM_ACTIVATE_UP);
+ 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:
+ break;
+
+ default:
+ break;
+ }
+
+ return EINA_TRUE;
+}
+
+EAPI void
+elm_access_action_cb_set(Evas_Object *obj, const Elm_Access_Action_Type type, const Elm_Access_Action_Cb cb, const void *data)
+{
+ Action_Info *a;
+ a = evas_object_data_get(obj, "_elm_access_action_info");
+
+ if (!a)
+ {
+ a = calloc(1, sizeof(Action_Info));
+ evas_object_data_set(obj, "_elm_access_action_info", a);
+ }
+
+ a->obj = obj;
+ a->fn[type].cb = cb;
+ a->fn[type].user_data = (void *)data;
}
EAPI void