summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukasz Stanislawski <l.stanislaws@samsung.com>2015-08-05 03:23:47 +0200
committerLukasz Stanislawski <l.stanislaws@samsung.com>2015-10-05 08:06:51 +0200
commitc57bed959e8984d928fc3dc8bf51f12f8d13731c (patch)
treeabd948d56b172b3dd6e832bb827c7c93acd5505a
parentd2bdd969aa30439d53fb68c9c3ef2bfd6b221fb4 (diff)
atspi: support org.a11y.atspi.Collection interface
org.a11y.atspi.Collection interface allows to perform fast search queries on accessibility objects tree. Due to lack of specification of collection interface this implementation base on gnome project implementation from https://git.gnome.org/browse/at-spi2-atk/. @feature
-rw-r--r--src/lib/elm_atspi_bridge.c720
1 files changed, 711 insertions, 9 deletions
diff --git a/src/lib/elm_atspi_bridge.c b/src/lib/elm_atspi_bridge.c
index 345ab6b9a..934115350 100644
--- a/src/lib/elm_atspi_bridge.c
+++ b/src/lib/elm_atspi_bridge.c
@@ -87,6 +87,7 @@ typedef struct _Elm_Atspi_Bridge_Data
87 Eldbus_Service_Interface *application; 87 Eldbus_Service_Interface *application;
88 Eldbus_Service_Interface *action; 88 Eldbus_Service_Interface *action;
89 Eldbus_Service_Interface *component; 89 Eldbus_Service_Interface *component;
90 Eldbus_Service_Interface *collection;
90 Eldbus_Service_Interface *editable_text; 91 Eldbus_Service_Interface *editable_text;
91 Eldbus_Service_Interface *image; 92 Eldbus_Service_Interface *image;
92 Eldbus_Service_Interface *selection; 93 Eldbus_Service_Interface *selection;
@@ -98,6 +99,19 @@ typedef struct _Elm_Atspi_Bridge_Data
98 Eina_Bool connected : 1; 99 Eina_Bool connected : 1;
99} Elm_Atspi_Bridge_Data; 100} Elm_Atspi_Bridge_Data;
100 101
102
103struct collection_match_rule {
104 Elm_Atspi_State_Set states;
105 AtspiCollectionMatchType statematchtype;
106 Eina_List *attributes;
107 AtspiCollectionMatchType attributematchtype;
108 uint64_t roles[2];
109 AtspiCollectionMatchType rolematchtype;
110 Eina_List *ifaces;
111 AtspiCollectionMatchType interfacematchtype;
112 Eina_Bool reverse : 1;
113};
114
101static Eo *_instance; 115static Eo *_instance;
102static int _init_count = 0; 116static int _init_count = 0;
103 117
@@ -644,6 +658,15 @@ _elm_atspi_state_set_to_atspi_state_set(Elm_Atspi_State_Set states)
644 return ret; 658 return ret;
645} 659}
646 660
661static Elm_Atspi_State_Set
662_atspi_state_set_to_elm_atspi_state_set(uint64_t states)
663{
664 //Currently Elm_Atspi_State and Atspi_State_Set are binary compatible,
665 //implement proper coversion when it will be needed.
666 Elm_Atspi_State_Set ret = states;
667 return ret;
668}
669
647static Eina_Hash* 670static Eina_Hash*
648_elm_atspi_state_hash_build(void) 671_elm_atspi_state_hash_build(void)
649{ 672{
@@ -2365,6 +2388,675 @@ static const Eldbus_Service_Interface_Desc application_iface_desc = {
2365 ATSPI_DBUS_INTERFACE_APPLICATION, NULL, NULL, application_properties, _application_properties_get, _application_properties_set 2388 ATSPI_DBUS_INTERFACE_APPLICATION, NULL, NULL, application_properties, _application_properties_get, _application_properties_set
2366}; 2389};
2367 2390
2391void
2392_collection_match_rule_free(struct collection_match_rule *rule)
2393{
2394 Elm_Atspi_Attribute *attr;
2395 eina_list_free(rule->ifaces);
2396 EINA_LIST_FREE(rule->attributes, attr)
2397 {
2398 eina_stringshare_del(attr->key);
2399 eina_stringshare_del(attr->value);
2400 }
2401}
2402
2403static void
2404_collection_roles_convert(uint64_t roles[2])
2405{
2406 // Currently elm roles and atspi roles are binary compatible.
2407 // Implement this function when it will be needed.
2408 (void)roles;
2409}
2410
2411static Eina_Bool
2412_collection_iter_match_rule_get(Eldbus_Message_Iter *iter, struct collection_match_rule *rule)
2413{
2414 Eldbus_Message_Iter *states_iter, *attrib_iter, *iter_arg, *role_iter, *ifc_iter;
2415 unsigned int *array;
2416 int array_count, state_match, attrib_match, role_match, ifc_match, reverse;
2417 const char *ifc_name;
2418
2419 if (!eldbus_message_iter_arguments_get(iter, "aiia{ss}iaiiasib", &states_iter, &state_match, &attrib_iter, &attrib_match, &role_iter, &role_match, &ifc_iter, &ifc_match, &reverse))
2420 {
2421 ERR("Unable to get message arguments");
2422 return EINA_FALSE;
2423 }
2424
2425 memset(rule, 0x0, sizeof(struct collection_match_rule));
2426 rule->statematchtype = state_match;
2427 rule->attributematchtype = attrib_match;
2428 rule->rolematchtype = role_match;
2429 rule->interfacematchtype = ifc_match;
2430 rule->reverse = reverse;
2431
2432 if (!eldbus_message_iter_fixed_array_get(states_iter, 'i', &array, &array_count))
2433 return EINA_FALSE;
2434
2435 //Roles according to libatspi impementation are transfered in 2-int element fixed bit array
2436 if (array_count != 2)
2437 {
2438 ERR("Unexpected states array size");
2439 return EINA_FALSE;
2440 }
2441 uint64_t states = ((uint64_t)array[0] | ((uint64_t)array[1] << 32));
2442 rule->states = _atspi_state_set_to_elm_atspi_state_set(states);
2443
2444 //Roles according to libatspi impementation are transfered in 4-int element fixed bit array
2445 if (!eldbus_message_iter_fixed_array_get(role_iter, 'i', &array, &array_count))
2446 return EINA_FALSE;
2447
2448 if (array_count != 4)
2449 {
2450 ERR("Unexpected roles array size");
2451 return EINA_FALSE;
2452 }
2453
2454 //convert atspi roles to elm_roles
2455 rule->roles[0] = ((uint64_t)array[0] | ((uint64_t)array[1] << 32));
2456 rule->roles[1] = ((uint64_t)array[2] | ((uint64_t)array[3] << 32));
2457
2458 _collection_roles_convert(rule->roles);
2459
2460 //Get matching properties
2461 while (eldbus_message_iter_get_and_next(attrib_iter, '{', &iter_arg))
2462 {
2463 const char *key, *value;
2464 if (eldbus_message_iter_arguments_get(iter_arg, "ss", &key, &value))
2465 {
2466 Elm_Atspi_Attribute *attrib = calloc(sizeof(Elm_Atspi_Attribute), 1);
2467 attrib->key = eina_stringshare_add(key);
2468 attrib->value = eina_stringshare_add(value);
2469 rule->attributes = eina_list_append(rule->attributes, attrib);
2470 }
2471 }
2472
2473 //Get interfaces to match
2474 while (eldbus_message_iter_get_and_next(ifc_iter, 's', &ifc_name))
2475 {
2476 const Eo_Class *class = NULL;
2477 if (!strcmp(ifc_name, "action"))
2478 class = ELM_INTERFACE_ATSPI_ACTION_MIXIN;
2479 else if (!strcmp(ifc_name, "component"))
2480 class = ELM_INTERFACE_ATSPI_COMPONENT_MIXIN;
2481 else if (!strcmp(ifc_name, "editabletext"))
2482 class = ELM_INTERFACE_ATSPI_EDITABLE_TEXT_INTERFACE;
2483 else if (!strcmp(ifc_name, "text"))
2484 class = ELM_INTERFACE_ATSPI_TEXT_INTERFACE;
2485 else if (!strcmp(ifc_name, "image"))
2486 class = ELM_INTERFACE_ATSPI_SELECTION_INTERFACE;
2487 else if (!strcmp(ifc_name, "value"))
2488 class = ELM_INTERFACE_ATSPI_VALUE_INTERFACE;
2489
2490 if (class)
2491 rule->ifaces = eina_list_append(rule->ifaces, class);
2492 else
2493 {
2494 _collection_match_rule_free(rule);
2495 return EINA_FALSE;
2496 }
2497 }
2498
2499 return EINA_TRUE;
2500}
2501
2502static Eina_Bool
2503_collection_match_interfaces_helper(Eo *obj, Eina_List *ifcs, Eina_Bool condition, Eina_Bool ret_if_true, Eina_Bool ret_if_false)
2504{
2505 Eo_Class *class;
2506 Eina_List *l;
2507
2508 EINA_LIST_FOREACH(ifcs, l, class)
2509 {
2510 if (eo_isa(obj, class) == condition)
2511 return ret_if_true;
2512 }
2513 return ret_if_false;
2514}
2515
2516static Eina_Bool
2517_collection_match_interfaces_lookup(Eo *obj, struct collection_match_rule *rule)
2518{
2519 Eina_Bool ret = EINA_FALSE;
2520
2521 switch (rule->interfacematchtype)
2522 {
2523 case ATSPI_Collection_MATCH_INVALID:
2524 ret = EINA_TRUE;
2525 break;
2526 case ATSPI_Collection_MATCH_ALL:
2527 ret = _collection_match_interfaces_helper(
2528 obj, rule->ifaces, EINA_FALSE, EINA_FALSE, EINA_TRUE);
2529 break;
2530 case ATSPI_Collection_MATCH_ANY:
2531 ret = _collection_match_interfaces_helper(
2532 obj, rule->ifaces, EINA_TRUE, EINA_TRUE, EINA_FALSE);
2533 break;
2534 case ATSPI_Collection_MATCH_NONE:
2535 ret = _collection_match_interfaces_helper(
2536 obj, rule->ifaces, EINA_TRUE, EINA_FALSE, EINA_TRUE);
2537 break;
2538 default:
2539 break;
2540 }
2541 return ret;
2542}
2543
2544static Eina_Bool
2545_collection_match_states_lookup(Eo *obj, struct collection_match_rule *rule)
2546{
2547 Eina_Bool ret = EINA_FALSE;
2548 Elm_Atspi_State_Set ss;
2549
2550 eo_do(obj, ss = elm_interface_atspi_accessible_state_set_get());
2551
2552 switch (rule->statematchtype)
2553 {
2554 case ATSPI_Collection_MATCH_INVALID:
2555 ret = EINA_TRUE;
2556 break;
2557 case ATSPI_Collection_MATCH_ALL:
2558 ret = (ss & rule->states) == rule->states;
2559 break;
2560 case ATSPI_Collection_MATCH_ANY:
2561 ret = (ss & rule->states) > 0;
2562 break;
2563 case ATSPI_Collection_MATCH_NONE:
2564 ret = (ss & rule->states) == 0;
2565 break;
2566 default:
2567 break;
2568 }
2569
2570 return ret;
2571}
2572
2573static Eina_Bool
2574_collection_match_roles_lookup(Eo *obj, struct collection_match_rule *rule)
2575{
2576 Eina_Bool ret = EINA_FALSE;
2577 Elm_Atspi_Role role;
2578 int64_t role_set;
2579
2580 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
2581
2582 if (role > 64)
2583 {
2584 role -= 64;
2585 role_set = rule->roles[1];
2586 }
2587 else
2588 role_set = rule->roles[0];
2589
2590 switch (rule->rolematchtype)
2591 {
2592 case ATSPI_Collection_MATCH_INVALID:
2593 ret = EINA_TRUE;
2594 break;
2595 case ATSPI_Collection_MATCH_ALL:
2596 case ATSPI_Collection_MATCH_ANY:
2597 ret = (role_set & (1ULL << role)) > 0;
2598 break;
2599 case ATSPI_Collection_MATCH_NONE:
2600 ret = (role_set & (1ULL << role)) == 0;
2601 break;
2602 default:
2603 break;
2604 }
2605
2606 return ret;
2607}
2608
2609static Eina_Bool
2610_collection_match_attributes_helper(Eina_List *obj_attribs, Eina_List *attribs, Eina_Bool compare, Eina_Bool ret_if_compare, Eina_Bool ret_default)
2611{
2612 Eina_List *l, *l2;
2613 Elm_Atspi_Attribute *attr, *attr2;
2614
2615 EINA_LIST_FOREACH(attribs, l, attr)
2616 {
2617 EINA_LIST_FOREACH(obj_attribs, l2, attr2)
2618 {
2619 if ((attr->key && attr2->key &&
2620 attr->value && attr2->value &&
2621 !strcmp(attr->key, attr2->key) &&
2622 !strcmp(attr->value, attr2->value)) == compare)
2623 {
2624 return ret_if_compare;
2625 }
2626 }
2627 }
2628
2629 return ret_default;
2630}
2631
2632static Eina_Bool
2633_collection_match_attributes_lookup(Eo *obj, struct collection_match_rule *rule)
2634{
2635 Eina_Bool ret = EINA_FALSE;
2636 Eina_List *obj_attribs;
2637
2638 eo_do(obj, obj_attribs = elm_interface_atspi_accessible_attributes_get());
2639
2640 switch (rule->attributematchtype)
2641 {
2642 case ATSPI_Collection_MATCH_INVALID:
2643 ret = EINA_TRUE;
2644 break;
2645 case ATSPI_Collection_MATCH_ALL:
2646 ret = _collection_match_attributes_helper(
2647 obj_attribs, rule->attributes, EINA_FALSE, EINA_FALSE, EINA_TRUE);
2648 break;
2649 case ATSPI_Collection_MATCH_ANY:
2650 ret = _collection_match_attributes_helper(
2651 obj_attribs, rule->attributes, EINA_TRUE, EINA_TRUE, EINA_FALSE);
2652 break;
2653 case ATSPI_Collection_MATCH_NONE:
2654 ret = _collection_match_attributes_helper(
2655 obj_attribs, rule->attributes, EINA_TRUE, EINA_FALSE, EINA_TRUE);
2656 break;
2657 default:
2658 break;
2659 }
2660
2661 elm_atspi_attributes_list_free(obj_attribs);
2662
2663 return ret;
2664}
2665
2666static int
2667_collection_sort_order_canonical(struct collection_match_rule *rule, Eina_List **ls,
2668 int count, int max,
2669 Eo *obj, long index, Eina_Bool flag,
2670 Eo *pobj, Eina_Bool recurse, Eina_Bool traverse)
2671{
2672 int i = index;
2673 Eina_List *children;
2674 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
2675 long acount = eina_list_count(children);
2676 Eina_Bool prev = pobj ? EINA_TRUE : EINA_FALSE;
2677
2678 for (; i < acount && (max == 0 || count < max); i++)
2679 {
2680 Eo *child = eina_list_nth(children, i);
2681
2682 if (prev && child == pobj)
2683 {
2684 eina_list_free(children);
2685 return count;
2686 }
2687
2688 if (flag && _collection_match_interfaces_lookup(child, rule)
2689 && _collection_match_states_lookup(child, rule)
2690 && _collection_match_roles_lookup(child, rule)
2691 && _collection_match_attributes_lookup(child, rule))
2692 {
2693 *ls = eina_list_append(*ls, child);
2694 count++;
2695 }
2696
2697 if (!flag)
2698 flag = EINA_TRUE;
2699
2700 if (recurse && traverse)
2701 count = _collection_sort_order_canonical(rule, ls, count,
2702 max, child, 0, EINA_TRUE,
2703 pobj, recurse, traverse);
2704 }
2705 eina_list_free(children);
2706 return count;
2707}
2708
2709static int
2710_collection_sort_order_reverse_canonical(struct collection_match_rule *rule, Eina_List **ls,
2711 int count, int max, Eo *obj, Eina_Bool flag, Eo *pobj)
2712{
2713 Eo *nextobj, *parent;
2714 long indexinparent;
2715 Eina_List *children;
2716
2717 /* This breaks us out of the recursion. */
2718 if (!obj || obj == pobj)
2719 {
2720 return count;
2721 }
2722
2723 /* Add to the list if it matches */
2724 if (flag && _collection_match_interfaces_lookup(obj, rule)
2725 && _collection_match_states_lookup(obj, rule)
2726 && _collection_match_roles_lookup(obj, rule)
2727 && _collection_match_attributes_lookup(obj, rule)
2728 && (max == 0 || count < max))
2729 {
2730 *ls = eina_list_append(*ls, obj);
2731 count++;
2732 }
2733
2734 if (!flag)
2735 flag = EINA_TRUE;
2736
2737 /* Get the current nodes index in it's parent and the parent object. */
2738 eo_do(obj,
2739 indexinparent = elm_interface_atspi_accessible_index_in_parent_get(),
2740 parent = elm_interface_atspi_accessible_parent_get());
2741
2742 if ((indexinparent > 0) && ((max == 0) || (count < max)))
2743 {
2744 /* there are still some siblings to visit so get the previous sibling
2745 and get it's last descendant.
2746 First, get the previous sibling */
2747 eo_do(parent, children = elm_interface_atspi_accessible_children_get());
2748 nextobj = eina_list_nth(children, indexinparent - 1);
2749 eina_list_free(children);
2750
2751 /* Now, drill down the right side to the last descendant */
2752 do {
2753 eo_do(nextobj, children = elm_interface_atspi_accessible_children_get());
2754 if (children) nextobj = eina_list_last_data_get(children);
2755 eina_list_free(children);
2756 } while (children);
2757
2758 /* recurse with the last descendant */
2759 count = _collection_sort_order_reverse_canonical(rule, ls, count, max,
2760 nextobj, EINA_TRUE, pobj);
2761 }
2762 else if (max == 0 || count < max)
2763 {
2764 /* no more siblings so next node must be the parent */
2765 count = _collection_sort_order_reverse_canonical(rule, ls, count, max,
2766 parent, EINA_TRUE, pobj);
2767
2768 }
2769 return count;
2770}
2771
2772static int
2773_collection_inbackorder(Eo *collection, struct collection_match_rule *rule, Eina_List **list,
2774 int max, Eo *obj)
2775{
2776 *list = eina_list_append(*list, obj);
2777
2778 _collection_sort_order_reverse_canonical(rule, list, 0, max, obj, EINA_TRUE, collection);
2779
2780 *list = eina_list_remove_list(*list, *list);
2781
2782 return 0;
2783}
2784
2785static int
2786_collection_inorder(Eo *collection, struct collection_match_rule *rule, Eina_List **list,
2787 int count, int max, Eo *obj, Eina_Bool traverse)
2788{
2789 int idx = 0;
2790
2791 count = _collection_sort_order_canonical(rule, list, count, max, obj, 0, EINA_TRUE, NULL, EINA_TRUE, traverse);
2792
2793 while ((max == 0 || count < max) && obj && obj != collection)
2794 {
2795 Eo *parent;
2796 eo_do(obj,
2797 parent = elm_interface_atspi_accessible_parent_get(),
2798 idx = elm_interface_atspi_accessible_index_in_parent_get());
2799 count = _collection_sort_order_canonical(rule, list, count, max, parent,
2800 idx + 1, EINA_TRUE, EINA_FALSE, EINA_TRUE, traverse);
2801 obj = parent;
2802 }
2803
2804 if (max == 0 || count < max)
2805 count = _collection_sort_order_canonical(rule, list, count, max,
2806 obj, idx + 1, EINA_TRUE, EINA_FALSE, EINA_TRUE, traverse);
2807
2808 return count;
2809}
2810
2811static int
2812_collection_query(struct collection_match_rule *rule, AtspiCollectionSortOrder sortby,
2813 Eina_List **list, int count, int max, Eo *obj, long index,
2814 Eina_Bool flag, Eo *pobj, Eina_Bool recurse, Eina_Bool traverse)
2815{
2816 switch (sortby)
2817 {
2818 case ATSPI_Collection_SORT_ORDER_CANONICAL:
2819 count = _collection_sort_order_canonical(rule, list, 0, max, obj, index, flag,
2820 pobj, recurse, traverse);
2821 break;
2822 case ATSPI_Collection_SORT_ORDER_REVERSE_CANONICAL:
2823 count = _collection_sort_order_canonical(rule, list, 0, max, obj, index, flag,
2824 pobj, recurse, traverse);
2825 *list = eina_list_reverse(*list);
2826 break;
2827 default:
2828 count = 0;
2829 WRN("Unhandled sort method");
2830 break;
2831 }
2832 return count;
2833}
2834
2835static Eldbus_Message*
2836_collection_return_msg_from_list(Elm_Atspi_Bridge *bridge, const Eldbus_Message *msg, const Eina_List *objs)
2837{
2838 Eldbus_Message *ret;
2839 const Eina_List *l;
2840 Eldbus_Message_Iter *iter, *array_iter;
2841 Eo *obj;
2842
2843 ret = eldbus_message_method_return_new(msg);
2844 if (!ret) return NULL;
2845
2846 iter = eldbus_message_iter_get(ret);
2847 array_iter = eldbus_message_iter_container_new(iter, 'a', "(so)");
2848
2849 EINA_LIST_FOREACH(objs, l, obj)
2850 {
2851 _bridge_object_register(bridge, obj);
2852 _bridge_iter_object_reference_append(bridge, array_iter, obj);
2853 }
2854
2855 eldbus_message_iter_container_close(iter, array_iter);
2856 return ret;
2857}
2858
2859static Eina_List*
2860_collection_get_matches_from_handle(Eo *collection, Eo *current, struct collection_match_rule *rule, AtspiCollectionSortOrder sortby, AtspiCollectionTreeTraversalType tree, int max, Eina_Bool traverse)
2861{
2862 Eina_List *result = NULL;
2863 Eo *parent;
2864 int idx;
2865
2866 switch (tree)
2867 {
2868 case ATSPI_Collection_TREE_INORDER:
2869 _collection_inorder(collection, rule, &result, 0, max, current, traverse);
2870 if (sortby == ATSPI_Collection_SORT_ORDER_REVERSE_CANONICAL)
2871 result = eina_list_reverse(result);
2872 break;
2873 case ATSPI_Collection_TREE_RESTRICT_CHILDREN:
2874 eo_do(current,
2875 idx = elm_interface_atspi_accessible_index_in_parent_get(),
2876 parent = elm_interface_atspi_accessible_parent_get());
2877 _collection_query(rule, sortby, &result, 0, max, parent, idx, EINA_FALSE, NULL, EINA_TRUE, traverse);
2878 break;
2879 case ATSPI_Collection_TREE_RESTRICT_SIBLING:
2880 _collection_query(rule, sortby, &result, 0, max, current, 0, EINA_FALSE, NULL, EINA_TRUE, traverse);
2881 break;
2882 default:
2883 ERR("Tree parameter value not handled");
2884 break;
2885 }
2886 return result;
2887}
2888
2889static Eldbus_Message*
2890_collection_get_matches_from(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED)
2891{
2892 const char *obj_path = eldbus_message_path_get(msg);
2893 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2894 Eo *current, *obj = _bridge_object_from_path(bridge, obj_path);
2895 Eldbus_Message *ret;
2896 Eldbus_Message_Iter *iter, *rule_iter;
2897 struct collection_match_rule rule;
2898 int count;
2899 AtspiCollectionTreeTraversalType tree;
2900 Eina_Bool traverse;
2901 AtspiCollectionSortOrder sortby;
2902 Eina_List *result = NULL;
2903
2904 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
2905
2906 iter = eldbus_message_iter_get(msg);
2907 EINA_SAFETY_ON_NULL_RETURN_VAL(iter, NULL);
2908
2909 if (!eldbus_message_iter_arguments_get(iter, "o(aiia{ss}iaiiasib)uuib", &obj_path, &rule_iter, &sortby, &tree, &count, &traverse))
2910 {
2911 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Unable to get matchule, sortby, count or traverse values.");
2912 }
2913
2914 current = _bridge_object_from_path(bridge, obj_path);
2915
2916 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(current, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
2917
2918 if (!_collection_iter_match_rule_get(rule_iter, &rule))
2919 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Invalid match rule parameters.");
2920
2921 result = _collection_get_matches_from_handle(obj, current, &rule, sortby, tree, count, traverse);
2922 ret = _collection_return_msg_from_list(bridge, msg, result);
2923
2924 eina_list_free(result);
2925 _collection_match_rule_free(&rule);
2926
2927 return ret;
2928}
2929
2930static Eina_List*
2931_collection_get_matches_to_handle(Eo *obj, Eo *current, struct collection_match_rule *rule, AtspiCollectionSortOrder sortby, AtspiCollectionTreeTraversalType tree, Eina_Bool limit, int max, Eina_Bool traverse)
2932{
2933 Eina_List *result = NULL;
2934 Eo *collection = obj;
2935
2936 if (limit)
2937 eo_do(obj, collection = elm_interface_atspi_accessible_parent_get());
2938
2939 switch (tree)
2940 {
2941 case ATSPI_Collection_TREE_INORDER:
2942 _collection_inbackorder(obj, rule, &result, max, current);
2943 if (sortby == ATSPI_Collection_SORT_ORDER_REVERSE_CANONICAL)
2944 result = eina_list_reverse(result);
2945 break;
2946 case ATSPI_Collection_TREE_RESTRICT_CHILDREN:
2947 _collection_query(rule, sortby, &result, 0, max, collection, 0, EINA_FALSE, current, EINA_TRUE, traverse);
2948 break;
2949 case ATSPI_Collection_TREE_RESTRICT_SIBLING:
2950 _collection_query(rule, sortby, &result, 0, max, collection, 0, EINA_FALSE, current, EINA_TRUE, traverse);
2951 break;
2952 default:
2953 ERR("Tree parameter value not handled");
2954 break;
2955 }
2956
2957 return result;
2958}
2959
2960static Eldbus_Message*
2961_collection_get_matches_to(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED)
2962{
2963 const char *obj_path = eldbus_message_path_get(msg);
2964 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
2965 Eo *current, *obj = _bridge_object_from_path(bridge, obj_path);
2966 Eldbus_Message *ret;
2967 Eldbus_Message_Iter *iter, *rule_iter;
2968 struct collection_match_rule rule;
2969 int count;
2970 AtspiCollectionTreeTraversalType tree;
2971 Eina_Bool traverse;
2972 AtspiCollectionSortOrder sortby;
2973 Eina_List *result = NULL;
2974 Eina_Bool limit;
2975
2976 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
2977
2978 iter = eldbus_message_iter_get(msg);
2979 EINA_SAFETY_ON_NULL_RETURN_VAL(iter, NULL);
2980
2981 if (!eldbus_message_iter_arguments_get(iter, "o(aiia{ss}iaiiasib)uubib", &obj_path, &rule_iter, &sortby, &tree, &limit, &count, &traverse))
2982 {
2983 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Unable to get matchule, sortby, tree, limit count or traverse values.");
2984 }
2985
2986 current = _bridge_object_from_path(bridge, obj_path);
2987
2988 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(current, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
2989
2990 if (!_collection_iter_match_rule_get(rule_iter, &rule))
2991 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Invalid match rule parameters.");
2992
2993 result = _collection_get_matches_to_handle(obj, current, &rule, sortby, tree, limit, count, traverse);
2994 ret = _collection_return_msg_from_list(bridge, msg, result);
2995
2996 eina_list_free(result);
2997 _collection_match_rule_free(&rule);
2998
2999 return ret;
3000}
3001
3002static Eldbus_Message*
3003_collection_get_matches(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
3004{
3005 const char *obj_path = eldbus_message_path_get(msg);
3006 Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
3007 Eo *obj = _bridge_object_from_path(bridge, obj_path);
3008 Eldbus_Message *ret;
3009 Eldbus_Message_Iter *iter, *rule_iter;
3010 struct collection_match_rule rule;
3011 int count;
3012 Eina_Bool traverse;
3013 AtspiCollectionSortOrder sortby;
3014 Eina_List *result = NULL;
3015
3016 ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN, msg);
3017
3018 iter = eldbus_message_iter_get(msg);
3019 EINA_SAFETY_ON_NULL_RETURN_VAL(iter, NULL);
3020
3021 if (!eldbus_message_iter_arguments_get(iter, "(aiia{ss}iaiiasib)uib", &rule_iter, &sortby, &count, &traverse))
3022 {
3023 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Unable to get matchule, sortby, count or traverse values.");
3024 }
3025
3026 if (!_collection_iter_match_rule_get(rule_iter, &rule))
3027 return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Invalid match rule parameters.");
3028
3029 _collection_query(&rule, sortby, &result, 0, count, obj, 0, EINA_TRUE, NULL, EINA_TRUE, traverse);
3030
3031 ret = _collection_return_msg_from_list(bridge, msg, result);
3032
3033 eina_list_free(result);
3034 _collection_match_rule_free(&rule);
3035
3036 return ret;
3037}
3038
3039static const Eldbus_Method collection_methods[] = {
3040 { "GetMatchesFrom",
3041 ELDBUS_ARGS({"o", "current_object"}, {"(aiia{ss}iaiiasib)", "match_rule"},
3042 {"u", "sortby"}, {"u", "tree"}, {"i", "count"}, {"b", "traverse"}),
3043 ELDBUS_ARGS({"a(so)", "objects"}), _collection_get_matches_from, 0 },
3044 { "GetMatchesTo",
3045 ELDBUS_ARGS({"o", "current_object"}, {"(aiia{ss}iaiiasib)", "match_rule"},
3046 {"u", "sortby"}, {"u", "tree"}, {"b", "limit_scope"},
3047 {"i", "count"}, {"b", "traverse"}),
3048 ELDBUS_ARGS({"a(so)", "objects"}), _collection_get_matches_to, 0 },
3049 { "GetMatches",
3050 ELDBUS_ARGS({"(aiia{ss}iaiiasib)", "match_rule"},
3051 {"u", "sortby"}, {"i", "count"}, {"b", "traverse"}),
3052 ELDBUS_ARGS({"a(so)", "objects"}), _collection_get_matches, 0 },
3053 { NULL, NULL, NULL, NULL, 0 }
3054};
3055
3056static const Eldbus_Service_Interface_Desc collection_iface_desc = {
3057 ATSPI_DBUS_INTERFACE_COLLECTION, collection_methods, NULL, NULL, NULL, NULL
3058};
3059
2368static void 3060static void
2369_bridge_iter_object_reference_append(Eo *bridge, Eldbus_Message_Iter *iter, const Eo *obj) 3061_bridge_iter_object_reference_append(Eo *bridge, Eldbus_Message_Iter *iter, const Eo *obj)
2370{ 3062{
@@ -2396,21 +3088,26 @@ _iter_interfaces_append(Eldbus_Message_Iter *iter, const Eo *obj)
2396 if (!iter_array) return; 3088 if (!iter_array) return;
2397 3089
2398 if (eo_isa(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN)) 3090 if (eo_isa(obj, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
2399 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_ACCESSIBLE); 3091 {
2400 if (eo_isa(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN)) 3092 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_ACCESSIBLE);
2401 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_COMPONENT); 3093 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_COLLECTION);
3094 }
2402 if (eo_isa(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN)) 3095 if (eo_isa(obj, ELM_INTERFACE_ATSPI_ACTION_MIXIN))
2403 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_ACTION); 3096 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_ACTION);
2404 if (eo_isa(obj, ELM_INTERFACE_ATSPI_VALUE_INTERFACE)) 3097 if (eo_isa(obj, ELM_ATSPI_APP_OBJECT_CLASS))
2405 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_VALUE); 3098 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_APPLICATION);
2406 if (eo_isa(obj, ELM_INTERFACE_ATSPI_IMAGE_MIXIN)) 3099 if (eo_isa(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN))
2407 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_IMAGE); 3100 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_COMPONENT);
2408 if (eo_isa(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE))
2409 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_TEXT);
2410 if (eo_isa(obj, ELM_INTERFACE_ATSPI_EDITABLE_TEXT_INTERFACE)) 3101 if (eo_isa(obj, ELM_INTERFACE_ATSPI_EDITABLE_TEXT_INTERFACE))
2411 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_EDITABLE_TEXT); 3102 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_EDITABLE_TEXT);
3103 if (eo_isa(obj, ELM_INTERFACE_ATSPI_IMAGE_MIXIN))
3104 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_IMAGE);
2412 if (eo_isa(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE)) 3105 if (eo_isa(obj, ELM_INTERFACE_ATSPI_SELECTION_INTERFACE))
2413 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_SELECTION); 3106 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_SELECTION);
3107 if (eo_isa(obj, ELM_INTERFACE_ATSPI_TEXT_INTERFACE))
3108 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_TEXT);
3109 if (eo_isa(obj, ELM_INTERFACE_ATSPI_VALUE_INTERFACE))
3110 eldbus_message_iter_basic_append(iter_array, 's', ATSPI_DBUS_INTERFACE_VALUE);
2414 3111
2415 eldbus_message_iter_container_close(iter, iter_array); 3112 eldbus_message_iter_container_close(iter, iter_array);
2416} 3113}
@@ -3478,6 +4175,7 @@ _interfaces_unregister(Eo *bridge)
3478 INTERFACE_SAFE_FREE(pd->interfaces.application); 4175 INTERFACE_SAFE_FREE(pd->interfaces.application);
3479 INTERFACE_SAFE_FREE(pd->interfaces.action); 4176 INTERFACE_SAFE_FREE(pd->interfaces.action);
3480 INTERFACE_SAFE_FREE(pd->interfaces.component); 4177 INTERFACE_SAFE_FREE(pd->interfaces.component);
4178 INTERFACE_SAFE_FREE(pd->interfaces.collection);
3481 INTERFACE_SAFE_FREE(pd->interfaces.editable_text); 4179 INTERFACE_SAFE_FREE(pd->interfaces.editable_text);
3482 INTERFACE_SAFE_FREE(pd->interfaces.image); 4180 INTERFACE_SAFE_FREE(pd->interfaces.image);
3483 INTERFACE_SAFE_FREE(pd->interfaces.selection); 4181 INTERFACE_SAFE_FREE(pd->interfaces.selection);
@@ -3559,6 +4257,10 @@ _interfaces_register(Eo *bridge)
3559 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &component_iface_desc); 4257 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &component_iface_desc);
3560 eldbus_service_object_data_set(pd->interfaces.component, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge); 4258 eldbus_service_object_data_set(pd->interfaces.component, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
3561 4259
4260 pd->interfaces.collection =
4261 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &collection_iface_desc);
4262 eldbus_service_object_data_set(pd->interfaces.collection, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);
4263
3562 pd->interfaces.editable_text = 4264 pd->interfaces.editable_text =
3563 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &editable_text_iface_desc); 4265 eldbus_service_interface_fallback_register(pd->a11y_bus, ELM_ACCESS_OBJECT_PATH_PREFIX2, &editable_text_iface_desc);
3564 eldbus_service_object_data_set(pd->interfaces.editable_text, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge); 4266 eldbus_service_object_data_set(pd->interfaces.editable_text, ELM_ATSPI_BRIDGE_CLASS_NAME, bridge);