}
//
+//TIZEN_ONLY(20171102): add scroll functions for Universal-Switch scroll's functionality
+static Eldbus_Message *
+_accessible_get_scrollable_element(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
+{
+ const char *obj_path = eldbus_message_path_get(msg);
+ Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
+ Eo *obj = _bridge_object_from_path(bridge, obj_path);
+
+ ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
+
+ while (obj)
+ {
+ if (eo_isa(obj, ELM_INTERFACE_SCROLLABLE_MIXIN)) break;
+ Eo *parent;
+ eo_do(obj, parent = elm_interface_atspi_accessible_parent_get());
+ obj = parent;
+ }
+
+ Eldbus_Message *ret = eldbus_message_method_return_new(msg);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
+
+ Eldbus_Message_Iter *iter = eldbus_message_iter_get(ret);
+ _bridge_iter_object_reference_append(bridge, iter, obj);
+ _bridge_object_register(bridge, obj);
+
+ return ret;
+}
+//
+
static const Eldbus_Method accessible_methods[] = {
// TIZEN_ONLY(20170310) - implementation of get object under coordinates for accessibility
{ "GetNavigableAtPoint", ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"u", "coord_type"}), ELDBUS_ARGS({"(so)y", "accessible"}, {"(so)", "deputy"}), _accessible_get_navigable_at_point, 0 },
{ "GetNeighbor", ELDBUS_ARGS({"s", "current"}, {"i", "direction"}, {"i", "force_next"}), ELDBUS_ARGS({"(so)y", "accessible"}), _accessible_get_neighbor, 0 },
//
+
+ //TIZEN_ONLY(20171102): add scroll functions for Universal-Switch scroll's functionality
+ { "GetScrollableElement", NULL, ELDBUS_ARGS({"(so)", "scrollable"}), _accessible_get_scrollable_element, 0 },
+ //
+
{ "GetChildAtIndex", ELDBUS_ARGS({"i", "index"}), ELDBUS_ARGS({"(so)", "Accessible"}), _accessible_child_at_index, 0 },
{ "GetChildren", NULL, ELDBUS_ARGS({"a(so)", "children"}), _accessible_get_children, 0 },
{ "GetIndexInParent", NULL, ELDBUS_ARGS({"i", "index"}), _accessible_get_index_in_parent, 0 },
return ret;
}
+// //TIZEN_ONLY(20171102): add scroll functions for Universal-Switch scroll's functionality
+
+static Eldbus_Message *
+_component_execute_scroll_auto(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
+{
+ const char *obj_path = eldbus_message_path_get(msg);
+ Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
+ Eo *obj = _bridge_object_from_path(bridge, obj_path);
+ Eldbus_Message *ret;
+
+ ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
+ if (!eo_isa(obj, ELM_INTERFACE_SCROLLABLE_MIXIN)) return _dbus_invalid_ref_error_new(msg);
+
+ unsigned int ustep;
+ int direction, step;
+ double remainingTime = 0;
+ if (!eldbus_message_arguments_get(msg, "iu", &direction, &ustep))
+ return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid argument types.");
+
+ if (direction != ELM_SCROLL_DIRECTION_UP && direction != ELM_SCROLL_DIRECTION_DOWN &&
+ direction != ELM_SCROLL_DIRECTION_LEFT && direction != ELM_SCROLL_DIRECTION_RIGHT)
+ return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid direction value.");
+
+ eo_do(obj, remainingTime = elm_interface_scrollable_content_scroll_auto(direction, ustep));
+
+ ret = eldbus_message_method_return_new(msg);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
+
+ eldbus_message_arguments_append(ret, "d", remainingTime);
+
+ return ret;
+}
+
+static Eldbus_Message *
+_component_execute_scroll_page(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
+{
+ const char *obj_path = eldbus_message_path_get(msg);
+ Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
+ Eo *obj = _bridge_object_from_path(bridge, obj_path);
+
+ ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
+ if (!eo_isa(obj, ELM_INTERFACE_SCROLLABLE_MIXIN)) return _dbus_invalid_ref_error_new(msg);
+
+ int direction;
+ if (!eldbus_message_arguments_get(msg, "i", &direction))
+ return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid argument type.");
+
+ if (direction != ELM_SCROLL_DIRECTION_UP && direction != ELM_SCROLL_DIRECTION_DOWN &&
+ direction != ELM_SCROLL_DIRECTION_LEFT && direction != ELM_SCROLL_DIRECTION_RIGHT)
+ return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid direction value.");
+
+ eo_do(obj, elm_interface_scrollable_content_scroll_page(direction));
+
+ return eldbus_message_method_return_new(msg);
+}
+
+static Eldbus_Message *
+_component_execute_scroll_to_end(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
+{
+ const char *obj_path = eldbus_message_path_get(msg);
+ Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
+ Eo *obj = _bridge_object_from_path(bridge, obj_path);
+
+ ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
+ if (!eo_isa(obj, ELM_INTERFACE_SCROLLABLE_MIXIN)) return _dbus_invalid_ref_error_new(msg);
+
+ int direction;
+ if (!eldbus_message_arguments_get(msg, "i", &direction))
+ return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid argument type.");
+
+ if (direction != ELM_SCROLL_DIRECTION_UP && direction != ELM_SCROLL_DIRECTION_DOWN &&
+ direction != ELM_SCROLL_DIRECTION_LEFT && direction != ELM_SCROLL_DIRECTION_RIGHT)
+ return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid direction value.");
+
+ eo_do(obj, elm_interface_scrollable_content_scroll_to_end(direction));
+
+ return eldbus_message_method_return_new(msg);
+}
+//
+
static const Eldbus_Method component_methods[] = {
{ "Contains", ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"u", "coord_type"}), ELDBUS_ARGS({"b", "contains"}), _component_contains, 0 },
{ "GetAccessibleAtPoint", ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"u", "coord_type"}), ELDBUS_ARGS({"(so)", "accessible"}), _component_get_accessible_at_point, 0 },
{ "SetPosition", ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"u", "coord_type"}), ELDBUS_ARGS({"b", "result"}), _component_set_position, 0 },
{ "SetSize", ELDBUS_ARGS({"i", "width"}, {"i", "height"}), ELDBUS_ARGS({"b", "result"}), _component_set_size, 0 },
+ //TIZEN_ONLY(20171102): add scroll functions for Universal-Switch scroll's functionality
+ { "ScrollAuto", ELDBUS_ARGS({"i", "direction"}, {"u", "step"}), ELDBUS_ARGS({"d", "remainingTime"}), _component_execute_scroll_auto, 0 },
+ { "ScrollPage", ELDBUS_ARGS({"i", "direction"}), NULL, _component_execute_scroll_page, 0 },
+ { "ScrollToEnd", ELDBUS_ARGS({"i", "direction"}), NULL, _component_execute_scroll_to_end, 0 },
+ //
+
//TIZEN_ONLY(20160329): atspi: implement HighlightGrab and HighlightClear methods (29e253e2f7ef3c632ac3a64c489bf569df407f30)
{ "GrabHighlight", NULL, ELDBUS_ARGS({"b", "result"}), _component_grab_highlight, 0 },
{ "ClearHighlight", NULL, ELDBUS_ARGS({"b", "result"}), _component_clear_highlight, 0 },
}
}
+//TIZEN_ONLY(20171102): add scroll functions for Universal-Switch scroll's functionality
+typedef struct scroll_timer_data {
+ Ecore_Timer *timer;
+ Eo *obj;
+ int step, start_pos, vertical;
+ double step_calc_time;
+ double end_time;
+} scroll_timer_data;
+static scroll_timer_data scroll_info;
+
+static double _scroll_timer_data_calculate(int *pos, int start_pos, int step, int size, int view,
+ double now, double step_calc_time)
+{
+ *pos = start_pos + step * (now - step_calc_time);
+
+ double timeToFinish = 0;
+
+ if (step > 0)
+ {
+ if (*pos + view > size)
+ {
+ *pos = size - view;
+ if (*pos < 0) *pos = 0;
+ }
+ else
+ {
+ timeToFinish = ((double)size - (*pos + view)) / step;
+ }
+ }
+ else if (step < 0)
+ {
+ if (*pos < 0)
+ {
+ *pos = 0;
+ }
+ else
+ {
+ timeToFinish = ((double)*pos) / -step;
+ }
+ }
+
+ if (timeToFinish < 0) timeToFinish = 0;
+
+ return timeToFinish;
+}
+
+static double _scroll_timer_data_update(double now, Eina_Bool force_reset)
+{
+ if (!scroll_info.obj) {
+ return 0;
+ }
+ int size_w, size_h, view_w, view_h, pos_x, pos_y;
+ eo_do(scroll_info.obj,
+ elm_interface_scrollable_content_pos_get(&pos_x, &pos_y),
+ elm_interface_scrollable_content_size_get(&size_w, &size_h),
+ elm_interface_scrollable_content_viewport_geometry_get(NULL, NULL, &view_w, &view_h));
+
+ double timeToFinish = 0;
+ if (scroll_info.vertical)
+ {
+ timeToFinish = _scroll_timer_data_calculate(&pos_y, scroll_info.start_pos, scroll_info.step,
+ size_h, view_h, now, scroll_info.step_calc_time);
+ if (force_reset) scroll_info.start_pos = pos_y;
+ }
+ else
+ {
+ timeToFinish = _scroll_timer_data_calculate(&pos_x, scroll_info.start_pos, scroll_info.step,
+ size_w, view_w, now, scroll_info.step_calc_time);
+ if (force_reset) scroll_info.start_pos = pos_x;
+ }
+ if (force_reset) scroll_info.step_calc_time = now;
+ eo_do(scroll_info.obj, elm_interface_scrollable_content_pos_set(pos_x, pos_y, EINA_TRUE));
+ return timeToFinish;
+}
+
+static Eina_Bool scroll_timer_cb(void *data)
+{
+ double now = ecore_time_get();
+ if (now >= scroll_info.end_time || _scroll_timer_data_update(now, EINA_FALSE) == 0)
+ {
+ scroll_info.timer = NULL;
+ return ECORE_CALLBACK_CANCEL;
+ }
+
+ return ECORE_CALLBACK_RENEW;
+}
+
+EOLIAN static double
+_elm_interface_scrollable_content_scroll_auto(Eo *obj EINA_UNUSED, Elm_Scrollable_Smart_Interface_Data *sid, Elm_Scroll_Direction direction, unsigned int ustep)
+{
+ double remainingTime = 0;
+
+ int step = (int)ustep;
+ if (step == 0)
+ {
+ remainingTime = 0;
+ if (scroll_info.timer)
+ {
+ ecore_timer_del(scroll_info.timer);
+ scroll_info.timer = NULL;
+ }
+ }
+ else
+ {
+ double now = ecore_time_get();
+ scroll_info.end_time = now + 1.0f;
+ scroll_info.vertical = direction == ELM_SCROLL_DIRECTION_UP || direction == ELM_SCROLL_DIRECTION_DOWN;
+
+ if (direction == ELM_SCROLL_DIRECTION_UP || direction == ELM_SCROLL_DIRECTION_LEFT) step = -step;
+
+ if (!scroll_info.timer || scroll_info.obj != obj)
+ {
+ scroll_info.obj = obj;
+ scroll_info.step_calc_time = now;
+ scroll_info.step = step;
+
+ if (scroll_info.vertical)
+ eo_do(obj, elm_interface_scrollable_content_pos_get(NULL, &scroll_info.start_pos));
+ else
+ eo_do(obj, elm_interface_scrollable_content_pos_get(&scroll_info.start_pos, NULL));
+ remainingTime = _scroll_timer_data_update(now, EINA_FALSE);
+ }
+ else
+ {
+ remainingTime = _scroll_timer_data_update(now, EINA_TRUE);
+ scroll_info.step = step;
+ }
+ // TODO: remove move by timer and some sort of animator object to animate scrolling
+ if (!scroll_info.timer) scroll_info.timer = ecore_timer_add(0.04f, scroll_timer_cb, NULL);
+ }
+ return remainingTime;
+}
+
+static void _scroll_page_calculate(int *pos, int size, int view, int positive_direction)
+{
+ if (positive_direction)
+ {
+ *pos += view;
+ if (*pos + view > size)
+ {
+ *pos = size - view;
+ if (*pos < 0) *pos = 0;
+ }
+ }
+ else
+ {
+ *pos -= view;
+ if (*pos < 0) *pos = 0;
+ }
+}
+
+EOLIAN static void
+_elm_interface_scrollable_content_scroll_page(Eo *obj EINA_UNUSED, Elm_Scrollable_Smart_Interface_Data *sid, Elm_Scroll_Direction direction)
+{
+ int size_w, size_h, view_w, view_h, pos_x, pos_y;
+ eo_do(obj,
+ elm_interface_scrollable_content_pos_get(&pos_x, &pos_y),
+ elm_interface_scrollable_content_size_get(&size_w, &size_h),
+ elm_interface_scrollable_content_viewport_geometry_get(NULL, NULL, &view_w, &view_h));
+
+ if (direction == ELM_SCROLL_DIRECTION_DOWN || direction == ELM_SCROLL_DIRECTION_UP)
+ _scroll_page_calculate(&pos_y, size_h, view_h, direction == ELM_SCROLL_DIRECTION_DOWN);
+ else
+ _scroll_page_calculate(&pos_x, size_w, view_w, direction == ELM_SCROLL_DIRECTION_RIGHT);
+
+ eo_do(obj, elm_interface_scrollable_region_bring_in(pos_x, pos_y, size_w, size_h));
+}
+
+EOLIAN static void
+_elm_interface_scrollable_content_scroll_to_end(Eo *obj EINA_UNUSED, Elm_Scrollable_Smart_Interface_Data *sid, Elm_Scroll_Direction direction)
+{
+ int size_w, size_h, view_w, view_h, pos_x, pos_y;
+ eo_do(obj,
+ elm_interface_scrollable_content_pos_get(&pos_x, &pos_y),
+ elm_interface_scrollable_content_size_get(&size_w, &size_h),
+ elm_interface_scrollable_content_viewport_geometry_get(NULL, NULL, &view_w, &view_h));
+
+ if (direction == ELM_SCROLL_DIRECTION_DOWN)
+ {
+ pos_y = size_h - view_h;
+ if (pos_y < 0) pos_y = 0;
+ }
+ else if (direction == ELM_SCROLL_DIRECTION_RIGHT)
+ {
+ pos_x = size_w - view_w;
+ if (pos_x < 0) pos_x = 0;
+ }
+ else if (direction == ELM_SCROLL_DIRECTION_LEFT)
+ {
+ pos_x = 0;
+ }
+ else if (direction == ELM_SCROLL_DIRECTION_UP)
+ {
+ pos_y = 0;
+ }
+
+ eo_do(obj, elm_interface_scrollable_region_bring_in(pos_x, pos_y, size_w, size_h));
+}
+//
+
EOLIAN static void
_elm_interface_scrollable_content_pos_get(Eo *obj EINA_UNUSED, Elm_Scrollable_Smart_Interface_Data *sid, Evas_Coord *x, Evas_Coord *y)
{