From 23b49ea6ed68e056d1d8de4756293ca026ec09ce Mon Sep 17 00:00:00 2001 From: Pawel Kurowski Date: Thu, 1 Jun 2017 12:45:08 +0200 Subject: [PATCH] Add relation-dump option to at_spi2_tool Flags -d and -c now inform when object has relations to list. Change-Id: I0c9a03c8d18ddf965c72ceac2bb804742c4540bf --- test/at_spi2_tool.c | 155 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 110 insertions(+), 45 deletions(-) diff --git a/test/at_spi2_tool.c b/test/at_spi2_tool.c index dfbc051..15adca5 100644 --- a/test/at_spi2_tool.c +++ b/test/at_spi2_tool.c @@ -5,6 +5,7 @@ #include #include #include +#include #define ERROR_STATE -1 #define SAFE_BUFFER_SIZE 2048 @@ -18,6 +19,8 @@ #define DUMP 0 #define CHECK 1 #define FIRST_MATCH 2 +#define RELATION_TABLE_COLUMN_COUNT 7 +#define RELATION_COLUMN_WIDTH 20 #define VERSION "1.1" static unsigned indent_width = 2; @@ -80,12 +83,6 @@ typedef struct _Box_Size { char *width; } Box_Size; -char *_strdup(const char *c) -{ - char *result = (char *)calloc(1, strlen(c) + 1); - return result ? strcpy(result, c) : result; -} - static char *_multiply_string(char c, unsigned number) { char *result = (char *)calloc(1, number + 1); @@ -100,7 +97,7 @@ static char *_multiply_string(char c, unsigned number) static void _print_module_legend() { - printf("\n[[node],[node role name],[attributes list],[x,y,width,height],[node name],[states list][flow to node, flow from node]\n\n"); + printf("\n[[node],[node role name],[attributes list],[x,y,width,height],[node name],[states list][relations]\n\n"); } static void _print_atspi_states_legend() @@ -251,7 +248,7 @@ static char *_get_states(AtspiAccessible *node, int length_limit) state_type = g_array_index(states, AtspiStateType, i); char node_state_str[8]; - sprintf(node_state_str, "(%d)", state_type); + snprintf(node_state_str, 8, "(%d)", state_type); _combine_strings(&state_string, node_state_str); } @@ -289,32 +286,6 @@ static char *_get_attributes(AtspiAccessible *node, int length_limit) return result; } -static char *_get_object_in_relation(AtspiAccessible *source, AtspiRelationType search_type) -{ - if (source == NULL) - return ""; - - GArray *relations = atspi_accessible_get_relation_set(source, NULL); - - if (relations == NULL) - return ""; - - AtspiAccessible *ret = NULL; - for (int i = 0; i < relations->len; ++i) { - AtspiRelation *relation = g_array_index(relations, AtspiRelation *, i); - AtspiRelationType type = atspi_relation_get_relation_type(relation); - - if (type == search_type) { - ret = atspi_relation_get_target(relation, 0); - break; - } - } - - g_array_free(relations, TRUE); - - return ret ? atspi_accessible_get_unique_id(ret, NULL) : g_strdup(""); -} - static char *_get_info(AtspiAccessible *node, int length_limit) { if (!node) @@ -328,11 +299,10 @@ static char *_get_info(AtspiAccessible *node, int length_limit) Box_Size *box_size = _get_box_size(node); char *states = _get_states(node, length_limit); - char *flows_to = _get_object_in_relation(node, ATSPI_RELATION_FLOWS_TO); - char *flows_from = _get_object_in_relation(node, ATSPI_RELATION_FLOWS_FROM); + GArray *relations = atspi_accessible_get_relation_set(node, NULL); char result[SAFE_BUFFER_SIZE]; - int ret = snprintf(result, SAFE_BUFFER_SIZE, "[[%s],[%s],[%s],[%s,%s,%s,%s],[%s],[%s],[%s,%s]]", + int ret = snprintf(result, SAFE_BUFFER_SIZE, "[[%s],[%s],[%s],[%s,%s,%s,%s],[%s],[%s],[%s]]", unique_id, node_role_name, attributes, @@ -342,8 +312,7 @@ static char *_get_info(AtspiAccessible *node, int length_limit) box_size->height, node_name, states, - flows_to, - flows_from); + (relations && relations->len) ? "*" : ""); if (ret >= SAFE_BUFFER_SIZE) fprintf(stderr, "\n%s, %s %d: generated string is too long. Buffer overflow\n", __FILE__, __FUNCTION__, __LINE__); @@ -358,10 +327,9 @@ static char *_get_info(AtspiAccessible *node, int length_limit) free(box_size); } free(states); - free(flows_to); - free(flows_from); + g_array_free(relations, TRUE); - return _strdup(result); + return g_strdup(result); } static void _test_atspi_parent_child_relation(AtspiAccessible *obj, AtspiAccessible *parent_candidate, int parent_candidate_index) @@ -374,7 +342,7 @@ static void _test_atspi_parent_child_relation(AtspiAccessible *obj, AtspiAccessi char parent_status[NUMBER_WIDTH]; if (parent == NULL) - strcpy(parent_status, "_"); + strncpy(parent_status, "_", NUMBER_WIDTH); else snprintf(parent_status, NUMBER_WIDTH, "%d", parent_index); @@ -441,11 +409,105 @@ void _print_help() printf("\tat_spi2_tool -i1 -c starter\n"); printf("\t show AT-SPI tree with integrity test for node \"starter\" using one-space indentation\n"); } + void _print_version() { printf("AT-SPI2-CORE-UTIL v%s\n", VERSION); } +static void _print_horizontal_line_in_relation_table() { + for (int i = 0; i < RELATION_TABLE_COLUMN_COUNT; i++) { + for (int j = 0; j < RELATION_COLUMN_WIDTH; j++) + printf("-"); + printf("+"); + } + printf("\n"); +} + +static void _print_legend_for_relation_table() { + char *table[] = {"OBJECT", "CONTROLLER_FOR", "CONTROLLED_BY", "FLOWS_TO", "FLOWS_FROM", "DESCRIBED_BY", "OTHER RELATION [ID]"}; + assert(ARRAY_SIZE(table) == RELATION_TABLE_COLUMN_COUNT); + for(int i = 0; i < RELATION_TABLE_COLUMN_COUNT; i++) + printf("%*s|", RELATION_COLUMN_WIDTH , table[i]); + printf("\n"); + _print_horizontal_line_in_relation_table(); +} + +static char *_get_unique_id_of_object_in_relation(AtspiRelation *relation) { + if (!relation) + return NULL; + + gint last_index = atspi_relation_get_n_targets(relation) - 1; + AtspiAccessible *target = atspi_relation_get_target(relation, last_index); + return atspi_accessible_get_unique_id(target, NULL); +} + +static void _print_relations_for_object(AtspiAccessible *node) { + GArray *relations = atspi_accessible_get_relation_set(node, NULL); + if (!relations) + return; + + if (!relations->len) { + g_array_free(relations, FALSE); + return; + } + + char **table = calloc(RELATION_TABLE_COLUMN_COUNT, sizeof(char *)); + if (!table) { + fprintf(stderr, "Calloc failed. Can't alloc memory for object relations string\n"); + return; + } + + table[0] = atspi_accessible_get_unique_id(node, NULL); + for (int i = 0; i < relations->len; i++) { + AtspiRelation *relation = g_array_index(relations, AtspiRelation *, i); + AtspiRelationType type = atspi_relation_get_relation_type(relation); + int idx; + switch (type) { + case ATSPI_RELATION_CONTROLLER_FOR: idx = 1; break; + case ATSPI_RELATION_CONTROLLED_BY: idx = 2; break; + case ATSPI_RELATION_FLOWS_TO: idx = 3; break; + case ATSPI_RELATION_FLOWS_FROM: idx = 4; break; + case ATSPI_RELATION_DESCRIBED_BY: idx = 5; break; + default: idx = 0; + } + + if (idx > 0) + table[idx] = _get_unique_id_of_object_in_relation(relation); + else { + char buf[16]; + snprintf(buf, sizeof(buf), " [%d]", type); + _combine_strings(&table[RELATION_TABLE_COLUMN_COUNT - 1], buf); + } + } + + for (int i = 0; i < RELATION_TABLE_COLUMN_COUNT; i++) { + printf("%*s|", RELATION_COLUMN_WIDTH, table[i] ? table[i] : ""); + free(table[i]); + } + free(table); + + printf("\n"); + _print_horizontal_line_in_relation_table(); + g_array_free(relations, TRUE); +} + +static void _print_relations_for_objects_in_tree(AtspiAccessible *node) { + _print_relations_for_object(node); + + int count = atspi_accessible_get_child_count(node, NULL); + for (int i = 0; i < count; i++) { + AtspiAccessible *child = atspi_accessible_get_child_at_index(node, i, NULL); + if (child) + _print_relations_for_objects_in_tree(child); + } +} + +static void _print_relations_table(AtspiAccessible *node) { + _print_legend_for_relation_table(); + _print_relations_for_objects_in_tree(node); +} + static void _atspi_tree_traverse(const char *app_name, bool dump, bool check, bool first_match, int length_limit) { @@ -460,7 +522,7 @@ static void _atspi_tree_traverse(const char *app_name, bool dump, bool check, bo for (int i = 0; i < count; i++) { AtspiAccessible *child = atspi_accessible_get_child_at_index(desktop, i, NULL); if (child == NULL) { - fprintf(stderr, "\n%s, %s %d: Null child occured. Results may be misleading.\n", __FILE__, __FUNCTION__, __LINE__); + fprintf(stderr, "\n%s, %s %d: Null application occured. Results may be misleading.\n", __FILE__, __FUNCTION__, __LINE__); continue; } @@ -478,12 +540,15 @@ static void _atspi_tree_traverse(const char *app_name, bool dump, bool check, bo _test_atspi_parent_child_relation(child, desktop, i); _print_atspi_tree_verify_maybe_r(0, child, check, length_limit); + printf("\n"); + _print_relations_table(child); if (first_match) { free(name); break; - } else + } else { printf("\n"); + } free(name); } -- 2.7.4