From d1b090e4819f7fc7744aa141b0c182a88c650e36 Mon Sep 17 00:00:00 2001 From: Tomasz Olszak Date: Thu, 3 Sep 2015 16:13:53 +0200 Subject: [PATCH 01/16] Fixed issue: bus-launcher didn't start screen-reader after reader crash. Change-Id: Ic19ae2b029a4bae79e1cd1cb7300f5d59acf5722 --- bus/at-spi-bus-launcher.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/bus/at-spi-bus-launcher.c b/bus/at-spi-bus-launcher.c index b6f7f01..73c8a73 100644 --- a/bus/at-spi-bus-launcher.c +++ b/bus/at-spi-bus-launcher.c @@ -705,6 +705,15 @@ void screen_reader_cb(keynode_t *node, void *user_data) if (ret < 0) return; + //check if process really exists (e.g didn't crash) + if (bl->pid > 0) + { + int err = kill(bl->pid,0); + //process doesn't exist + if (err == ESRCH) + bl->pid = 0; + } + bl->screen_reader_needed = ret; LOGD("bl->screen_reader_needed: %i, bl->pid: %i", ret, bl->pid); if (!bl->screen_reader_needed && (bl->pid > 0)) -- 2.7.4 From 16bca52aaf6a590d26dcc073eeaf26fd2780ff58 Mon Sep 17 00:00:00 2001 From: Tomasz Olszak Date: Tue, 13 Oct 2015 16:05:34 +0200 Subject: [PATCH 02/16] Fixed crash during deregistering applications. Change-Id: I402bc5d6ed5f9ea503c4b310ec3c4fb9a85ca199 --- registryd/registry.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/registryd/registry.c b/registryd/registry.c index c533eb0..15bc7a9 100644 --- a/registryd/registry.c +++ b/registryd/registry.c @@ -144,11 +144,12 @@ find_index_of_reference (GPtrArray *arr, const gchar *name, const gchar * path, ref = spi_reference_new (name, path); - for (i = 0; i < arr->len && found == FALSE; i++) + for (i = 0; i < arr->len; i++) { if (compare_reference (ref, g_ptr_array_index (arr, i))); { found = TRUE; + break; } } -- 2.7.4 From 50ca96de84baae4d908d557b2a6ab39c9db02f92 Mon Sep 17 00:00:00 2001 From: Zbigniew Kosinski Date: Tue, 4 Nov 2014 15:57:36 +0100 Subject: [PATCH 03/16] Implement GrabHighlight and ClearHighligh methods. This commit adds support for new AtkComponent method interfaces. Change-Id: I66de60a86a308dc40107cf65d33c99dcbb1eaab2 Signed-off-by: Lukasz Stanislawski --- atspi/atspi-component.c | 40 ++++++++++++++++++++++++++++++++++++++++ atspi/atspi-component.h | 4 ++++ registryd/introspection.c | 8 ++++++++ registryd/registry.c | 28 ++++++++++++++++++++++++++++ 4 files changed, 80 insertions(+) diff --git a/atspi/atspi-component.c b/atspi/atspi-component.c index 0ab552b..41adeef 100644 --- a/atspi/atspi-component.c +++ b/atspi/atspi-component.c @@ -271,6 +271,46 @@ atspi_component_grab_focus (AtspiComponent *obj, GError **error) } /** + * atspi_component_grab_highlight: + * @obj: a pointer to the #AtspiComponent on which to operate. + * + * Attempts to set highlight to the specified + * #AtspiComponent. + * + * Returns: #TRUE if successful, #FALSE otherwise. + * + **/ +gboolean +atspi_component_grab_highlight (AtspiComponent *obj, GError **error) +{ + dbus_bool_t retval = FALSE; + + _atspi_dbus_call (obj, atspi_interface_component, "GrabHighlight", error, "=>b", &retval); + + return retval; +} + +/** + * atspi_component_clear_highlight: + * @obj: a pointer to the #AtspiComponent on which to operate. + * + * Attempts to clear highlight on the specified + * #AtspiComponent. + * + * Returns: #TRUE if successful, #FALSE otherwise. + * + **/ +gboolean +atspi_component_clear_highlight (AtspiComponent *obj, GError **error) +{ + dbus_bool_t retval = FALSE; + + _atspi_dbus_call (obj, atspi_interface_component, "ClearHighlight", error, "=>b", &retval); + + return retval; +} + +/** * atspi_component_get_alpha: * @obj: The #AtspiComponent to be queried. * diff --git a/atspi/atspi-component.h b/atspi/atspi-component.h index dd3455a..f5ddc62 100644 --- a/atspi/atspi-component.h +++ b/atspi/atspi-component.h @@ -107,6 +107,10 @@ gboolean atspi_component_set_position (AtspiComponent *obj, gint x, gint y, Atsp gboolean atspi_component_set_size (AtspiComponent *obj, gint width, gint height, GError **error); +gboolean atspi_component_grab_highlight (AtspiComponent *obj, GError **error); + +gboolean atspi_component_clear_highlight (AtspiComponent *obj, GError **error); + G_END_DECLS #endif /* _ATSPI_COMPONENT_H_ */ diff --git a/registryd/introspection.c b/registryd/introspection.c index edcf60d..84ce759 100644 --- a/registryd/introspection.c +++ b/registryd/introspection.c @@ -226,6 +226,14 @@ const char *spi_org_a11y_atspi_Component = " " " " "" +" " +" " +" " +"" +" " +" " +" " +"" " " " " " " diff --git a/registryd/registry.c b/registryd/registry.c index 15bc7a9..0a4e378 100644 --- a/registryd/registry.c +++ b/registryd/registry.c @@ -541,6 +541,30 @@ impl_GrabFocus (DBusConnection * bus, DBusMessage * message, void *user_data) } static DBusMessage * +impl_ClearHighlight (DBusConnection * bus, DBusMessage * message, void *user_data) +{ + DBusMessage *reply; + dbus_bool_t retval = FALSE; + + reply = dbus_message_new_method_return (message); + dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &retval, + DBUS_TYPE_INVALID); + return reply; +} + +static DBusMessage * +impl_GrabHighlight (DBusConnection * bus, DBusMessage * message, void *user_data) +{ + DBusMessage *reply; + dbus_bool_t retval = FALSE; + + reply = dbus_message_new_method_return (message); + dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &retval, + DBUS_TYPE_INVALID); + return reply; +} + +static DBusMessage * impl_GetAlpha (DBusConnection * bus, DBusMessage * message, void *user_data) { double rv = 1.0; @@ -1247,6 +1271,10 @@ handle_method_root (DBusConnection *bus, DBusMessage *message, void *user_data) reply = impl_GetMDIZOrder (bus, message, user_data); else if (!strcmp (member, "GrabFocus")) reply = impl_GrabFocus (bus, message, user_data); + else if (!strcmp (member, "GrabHighlight")) + reply = impl_GrabHighlight (bus, message, user_data); + else if (!strcmp (member, "ClearHighlight")) + reply = impl_ClearHighlight (bus, message, user_data); else if (!strcmp (member, "GetAlpha")) reply = impl_GetAlpha (bus, message, user_data); else -- 2.7.4 From 6e74f73487ccbb8c914ea3857498aeeae707f3a0 Mon Sep 17 00:00:00 2001 From: Lukasz Stanislawski Date: Tue, 12 May 2015 12:12:17 +0200 Subject: [PATCH 04/16] component: add component highlight index getter. Change-Id: I0500fe1a2a509c55ee87627db4ff56d3e2b429dd Signed-off-by: Lukasz Stanislawski --- atspi/atspi-component.c | 17 +++++++++++++++++ atspi/atspi-component.h | 2 ++ 2 files changed, 19 insertions(+) diff --git a/atspi/atspi-component.c b/atspi/atspi-component.c index 41adeef..bdbe57c 100644 --- a/atspi/atspi-component.c +++ b/atspi/atspi-component.c @@ -452,6 +452,23 @@ atspi_component_set_size (AtspiComponent *obj, return ret; } +/** + * atspi_component_get_highlight_index + * @obj: a pointer to the #AtspiComponent to query. + * + * Returns: highlight index of object if (>0), 0 if highlight index is not set + * or -1 if an error occured. + **/ +int +atspi_component_get_highlight_index (AtspiComponent *obj, GError **error) +{ + gint ret = -1; + g_return_val_if_fail (obj != NULL, -1); + _atspi_dbus_get_property (obj, atspi_interface_component, + "HighlightIndex", error, "i", &ret); + return ret; +} + static void atspi_component_base_init (AtspiComponent *klass) { diff --git a/atspi/atspi-component.h b/atspi/atspi-component.h index f5ddc62..1388072 100644 --- a/atspi/atspi-component.h +++ b/atspi/atspi-component.h @@ -111,6 +111,8 @@ gboolean atspi_component_grab_highlight (AtspiComponent *obj, GError **error); gboolean atspi_component_clear_highlight (AtspiComponent *obj, GError **error); +int atspi_component_get_highlight_index(AtspiComponent *obj, GError **error); + G_END_DECLS #endif /* _ATSPI_COMPONENT_H_ */ -- 2.7.4 From 7adcda8ac54e38e3390e4c67fc29c22c653d98c0 Mon Sep 17 00:00:00 2001 From: Shinwoo Kim Date: Mon, 7 Mar 2016 14:58:50 +0900 Subject: [PATCH 05/16] [Package Upload] 2.16.1 Change-Id: I19d1d302454a53c6aa840656d558709eb1db6d0a --- packaging/at-spi2-core.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/at-spi2-core.spec b/packaging/at-spi2-core.spec index 228b03f..cccfc55 100644 --- a/packaging/at-spi2-core.spec +++ b/packaging/at-spi2-core.spec @@ -2,7 +2,7 @@ %bcond_with x Name: at-spi2-core -Version: 2.16.0 +Version: 2.16.1 Release: 0 Summary: Assistive Technology Service Provider Interface - D-Bus based implementation License: LGPL-2.0+ -- 2.7.4 From 6f59ad8873ddca1d34d3238166c7820ef5b3c115 Mon Sep 17 00:00:00 2001 From: Shinwoo Kim Date: Thu, 14 Apr 2016 11:47:58 +0900 Subject: [PATCH 06/16] [License] Fix improper COPYING file installation Change-Id: Ic8c4ed69ae448f63b1611641ccce0de61eda9ac9 --- packaging/at-spi2-core.spec | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packaging/at-spi2-core.spec b/packaging/at-spi2-core.spec index cccfc55..ad24f8d 100644 --- a/packaging/at-spi2-core.spec +++ b/packaging/at-spi2-core.spec @@ -84,8 +84,6 @@ rm -rf %{buildroot} find %{buildroot} -name '*.la' -or -name '*.a' | xargs rm -f %make_install %find_lang %{name} -mkdir -p %{buildroot}/%{_datadir}/usr/share/license -cp -f %{_builddir}/%{buildsubdir}/COPYING %{buildroot}/%{_datadir}/usr/share/license/%{name} %check @@ -100,14 +98,13 @@ rm -fr %{buildroot} %manifest %{name}.manifest %defattr(-,root,root) %doc AUTHORS README -#%license COPYING +%license COPYING %{_libexecdir}/at-spi2/at-spi-bus-launcher %{_libexecdir}/at-spi2/at-spi2-registryd %config %{_sysconfdir}/at-spi2/accessibility.conf %{_sysconfdir}/xdg/autostart/at-spi-dbus-bus.desktop %{_datadir}/dbus-1/accessibility-services/org.a11y.atspi.Registry.service %{_datadir}/dbus-1/services/org.a11y.Bus.service -%{_datadir}/usr/share/license/%{name} %files -n libatspi0 %manifest %{name}.manifest @@ -124,4 +121,3 @@ rm -fr %{buildroot} %{_includedir}/at-spi-2.0 %{_libdir}/libatspi.so %{_libdir}/pkgconfig/atspi-2.pc - -- 2.7.4 From 65a8179bd64640d3c76767121dbf45ce9b8422ae Mon Sep 17 00:00:00 2001 From: "shashank.p" Date: Wed, 18 May 2016 14:58:19 +0530 Subject: [PATCH 07/16] Kill Screen-reader via SIGTERM only if aul_terminate_pid fails(returns a negative value) Change-Id: I8e863f3cc0acc11306eeb6a7e2fce50c9e75b65a Signed-off-by: shashank.p --- bus/at-spi-bus-launcher.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/bus/at-spi-bus-launcher.c b/bus/at-spi-bus-launcher.c index 73c8a73..3f6c917 100644 --- a/bus/at-spi-bus-launcher.c +++ b/bus/at-spi-bus-launcher.c @@ -663,6 +663,7 @@ _terminate_screen_reader(A11yBusLauncher *bl) { LOGD("Terminating screen reader"); int ret; + int ret_aul; if (bl->pid <= 0) return FALSE; @@ -677,11 +678,15 @@ _terminate_screen_reader(A11yBusLauncher *bl) } LOGD("terminate process with pid %d", bl->pid); - if (!aul_terminate_pid(bl->pid)) + ret_aul = aul_terminate_pid(bl->pid); + if (ret_aul >= 0) { + LOGD("Terminating with aul_terminate_pid: return is %d", ret_aul); bl->pid = 0; return TRUE; } + else + LOGD("aul_terminate_pid failed: return is %d", ret_aul); LOGD("Unable to terminate process using aul api. Sending SIGTERM signal"); ret = kill(bl->pid, SIGTERM); -- 2.7.4 From 632107d94461024f2cdcb6bbe530cc14e96f3fe0 Mon Sep 17 00:00:00 2001 From: Shinwoo Kim Date: Wed, 3 Jun 2015 20:30:57 +0900 Subject: [PATCH 08/16] Apply address space layout randomization (ASLR) Conflicts: bus/Makefile.am Change-Id: Ifbe933b90f357c0a179175333d57edc88b6c2316 --- bus/Makefile.am | 3 ++- registryd/Makefile.am | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/bus/Makefile.am b/bus/Makefile.am index 574e0ad..8e0eec6 100644 --- a/bus/Makefile.am +++ b/bus/Makefile.am @@ -7,8 +7,9 @@ libexec_PROGRAMS = at-spi-bus-launcher at_spi_bus_launcher_SOURCES = at-spi-bus-launcher.c at_spi_bus_launcher_CPPFLAGS = -DSYSCONFDIR=\"$(sysconfdir)\" \ -DDBUS_DAEMON=\"$(DBUS_DAEMON)\" -at_spi_bus_launcher_CFLAGS = $(GIO_CFLAGS) $(APPSVC_CFLAGS) $(VCONF_CFLAGS) $(AUL_CFLAGS) +at_spi_bus_launcher_CFLAGS = $(GIO_CFLAGS) $(APPSVC_CFLAGS) $(VCONF_CFLAGS) $(AUL_CFLAGS) -fPIE at_spi_bus_launcher_LDADD = $(GIO_LIBS) $(X_LIBS) $(APPSVC_LIBS) $(VCONF_LIBS) $(AUL_LIBS) +at_spi_bus_launcher_LDFLAGS = -pie default_sessiondir = $(sysconfdir)/xdg/autostart default_session_DATA = at-spi-dbus-bus.desktop diff --git a/registryd/Makefile.am b/registryd/Makefile.am index c9c9d39..1e2e953 100644 --- a/registryd/Makefile.am +++ b/registryd/Makefile.am @@ -1,6 +1,8 @@ libexec_PROGRAMS = at-spi2-registryd +at_spi2_registryd_LDFLAGS = -pie at_spi2_registryd_CFLAGS = \ + -fPIE \ $(GLIB_CFLAGS) \ $(GIO_CFLAGS) \ $(DBUS_CFLAGS) \ -- 2.7.4 From aa29c756e51d95c2d1611035690cb0c764193c73 Mon Sep 17 00:00:00 2001 From: Lukasz Wlazly Date: Mon, 19 Sep 2016 16:01:38 +0200 Subject: [PATCH 09/16] Tool for checking AT-SPI tree integrity v0.5 Tool is placed in /bin/ To check AT-SPI tree user "owner" must be set: su - owner Change-Id: I5da4bcaba19547695ae46242f5bbf2dbce7c411c --- packaging/at-spi2-core.spec | 3 + test/Makefile.am | 12 +- test/at_spi2_tool.c | 373 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 383 insertions(+), 5 deletions(-) create mode 100644 test/at_spi2_tool.c diff --git a/packaging/at-spi2-core.spec b/packaging/at-spi2-core.spec index ad24f8d..472f089 100644 --- a/packaging/at-spi2-core.spec +++ b/packaging/at-spi2-core.spec @@ -82,6 +82,7 @@ cp %{SOURCE1001} . %install rm -rf %{buildroot} find %{buildroot} -name '*.la' -or -name '*.a' | xargs rm -f + %make_install %find_lang %{name} @@ -97,6 +98,8 @@ rm -fr %{buildroot} %files -f %{name}.lang %manifest %{name}.manifest %defattr(-,root,root) +%{_bindir}/at_spi2_tool + %doc AUTHORS README %license COPYING %{_libexecdir}/at-spi2/at-spi-bus-launcher diff --git a/test/Makefile.am b/test/Makefile.am index 7af2ee0..f233c36 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,8 +1,10 @@ LDADD = $(top_builddir)/atspi/libatspi.la -noinst_PROGRAMS = memory -memory_SOURCES = memory.c -memory_CPPFLAGS = -I$(top_srcdir) -I$(top_builddir) -I$(top_builddir)/atspi -memory_CFLAGS = $(GLIB_CFLAGS) $(GOBJ_LIBS) $(DBUS_CFLAGS) -memory_LDFLAGS = +bin_PROGRAMS = at_spi2_tool +at_spi2_tool_SOURCES = at_spi2_tool.c +at_spi2_tool_CPPFLAGS = -I$(top_srcdir) -I$(top_builddir) -I$(top_builddir)/atspi +at_spi2_tool_CFLAGS = $(GLIB_CFLAGS) --std=c99 $(GOBJ_LIBS) $(DBUS_CFLAGS) +at_spi2_tool_LDFLAGS = + + -include $(top_srcdir)/git.mk diff --git a/test/at_spi2_tool.c b/test/at_spi2_tool.c new file mode 100644 index 0000000..f67700d --- /dev/null +++ b/test/at_spi2_tool.c @@ -0,0 +1,373 @@ +#include "atspi/atspi.h" +#include +#include +#include +#include +#include + +#define ERROR_STATE -1 +#define SAFE_BUFFER_SIZE 255 +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#define COLUMN_NO 3 + +static unsigned indent_width = 2; + +static const char* atspi_state_names[] = { + [ATSPI_STATE_INVALID] = "INVALID", + [ATSPI_STATE_ACTIVE] = "ACTIVE", + [ATSPI_STATE_ARMED] = "ARMED", + [ATSPI_STATE_BUSY] = "BUSY", + [ATSPI_STATE_CHECKED] = "CHECKED", + [ATSPI_STATE_COLLAPSED] = "COLLAPSED", + [ATSPI_STATE_DEFUNCT] = "DEFUNCT", + [ATSPI_STATE_EDITABLE] = "EDITABLE", + [ATSPI_STATE_ENABLED] = "ENABLED", + [ATSPI_STATE_EXPANDABLE] = "EXPANDABLE", + [ATSPI_STATE_EXPANDED] = "EXPANDED", + [ATSPI_STATE_FOCUSABLE] = "FOCUSABLE", + [ATSPI_STATE_FOCUSED] = "FOCUSED", + [ATSPI_STATE_HAS_TOOLTIP] = "HAS_TOOLTIP", + [ATSPI_STATE_HORIZONTAL] = "HORIZONTAL", + [ATSPI_STATE_ICONIFIED] = "ICONIFIED", + [ATSPI_STATE_MULTI_LINE] = "MULTI_LINE", + [ATSPI_STATE_MULTISELECTABLE] = "MULTISELECTABLE", + [ATSPI_STATE_OPAQUE] = "OPAQUE", + [ATSPI_STATE_PRESSED] = "PRESSED", + [ATSPI_STATE_RESIZABLE] = "RESIZABLE", + [ATSPI_STATE_SELECTABLE] = "SELECTABLE", + [ATSPI_STATE_SELECTED] = "SELECTED", + [ATSPI_STATE_SENSITIVE] = "SENSITIVE", + [ATSPI_STATE_SHOWING] = "SHOWING", + [ATSPI_STATE_SINGLE_LINE] = "SINGLE_LINE", + [ATSPI_STATE_STALE] = "STALE", + [ATSPI_STATE_TRANSIENT] = "TRANSIENT", + [ATSPI_STATE_VERTICAL] = "VERTICAL", + [ATSPI_STATE_VISIBLE] = "VISIBLE", + [ATSPI_STATE_MANAGES_DESCENDANTS] = "MANAGES_DESCENDANTS", + [ATSPI_STATE_INDETERMINATE] = "INDETERMINATE", + [ATSPI_STATE_REQUIRED] = "REQUIRED", + [ATSPI_STATE_TRUNCATED] = "TRUNCATED", + [ATSPI_STATE_ANIMATED] = "ANIMATED", + [ATSPI_STATE_INVALID_ENTRY] = "INVALID_ENTRY", + [ATSPI_STATE_SUPPORTS_AUTOCOMPLETION] = "SUPPORTS_AUTOCOMPLETION", + [ATSPI_STATE_SELECTABLE_TEXT] = "SELECTABLE_TEXT", + [ATSPI_STATE_IS_DEFAULT] = "IS_DEFAULT", + [ATSPI_STATE_VISITED] = "VISITED", + [ATSPI_STATE_CHECKABLE] = "CHECKABLE", + [ATSPI_STATE_MODAL] = "MODAL", + [ATSPI_STATE_HIGHLIGHTED] = "HIGHLIGHTED", + [ATSPI_STATE_HIGHLIGHTABLE] = "HIGHLIGHTABLE", + [ATSPI_STATE_HAS_POPUP] = "HAS_POPUP", + [ATSPI_STATE_READ_ONLY] = "READ_ONLY", + [ATSPI_STATE_LAST_DEFINED] = "LAST_DEFINED" +}; + +typedef struct _StringAccumulator { + char *string; + int length; +} StringAccumulator; + +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); + + if (result == NULL) + return result; + + memset(result, c, number); + + return result; +} + +static void _print_atspi_states_legend() { + int array_len = ARRAY_SIZE(atspi_state_names); + int line_count = (array_len + COLUMN_NO - 1)/COLUMN_NO; + for (int line_idx = 0; line_idx < line_count; line_idx++) { + if ((line_idx < line_count - 1) || (array_len % 3 == 0)) { + printf("[%d]\t%-24s[%d]\t%-24s[%d]\t%s\n", line_idx * 3, atspi_state_names[line_idx * 3], (line_idx * 3) + 1, atspi_state_names[(line_idx * 3) + 1], (line_idx * 3) + 2, atspi_state_names[(line_idx * 3) + 2]); + } else if (array_len % 3 == 2) { + printf("[%d]\t%-24s[%d]\t%s\n", line_idx * 3, atspi_state_names[line_idx * 3], (line_idx * 3) + 1, atspi_state_names[(line_idx * 3) + 1]); + } else { + printf("[%d]\t%s\n", line_idx * 3, atspi_state_names[line_idx * 3]); + } + } +} + +static void set_indent(int indent_size) +{ + if (indent_size < 0) { + fprintf(stderr, "WARNING: Invalid indent size. Default value retained.\n"); + return; + } + + indent_width = indent_size; +} + +static int _int_sort_function(gconstpointer a, gconstpointer b) +{ + int int_a = GPOINTER_TO_INT (a); + int int_b = GPOINTER_TO_INT (b); + + return int_a - int_b; +} + +static int _accumulate_string(const char *string, StringAccumulator *accumulator) { + if (!accumulator) + return FALSE; + + if (string) { + int length = accumulator->length + strlen(string); + char *rebuffer = realloc(accumulator->string, length + 1); + if (rebuffer) { + strcpy(rebuffer + accumulator->length, string); + accumulator->string = rebuffer; + accumulator->length = length; + } else { + return FALSE; + } + } + return TRUE; +} + +static char *get_info(AtspiAccessible *node) { + if (!node) + return NULL; + + int node_width = -1; + int node_height = -1; + char *node_name = atspi_accessible_get_name(node, NULL); + char *node_role_name = atspi_accessible_get_role_name(node, NULL); + AtspiComponent *component = atspi_accessible_get_component_iface(node); + + AtspiRect *extent = NULL; + if (component != NULL){ + extent = atspi_component_get_extents(component, ATSPI_COORD_TYPE_SCREEN, NULL); + + if (extent != NULL) { + node_width = extent->width; + node_height = extent->height; + } + } + + AtspiStateSet *node_state_set = atspi_accessible_get_state_set(node); + GArray *states = atspi_state_set_get_states(node_state_set); + g_array_sort(states, _int_sort_function); + + AtspiStateType state; + StringAccumulator state_accumulator = {}; + for (int i = 0; states && (i < states->len); i++) { + state = g_array_index(states, AtspiStateType, i); + char node_state_str[8]; + sprintf(node_state_str, "[%d]", state); + _accumulate_string(node_state_str, &state_accumulator); + } + g_array_free(states, 0); + + StringAccumulator attribute_accumulator = {}; + GHashTable *attributes = NULL; + attributes = atspi_accessible_get_attributes(node, NULL); + if (attributes) { + GHashTableIter attributes_iter; + gpointer attr_key, attr_value; + g_hash_table_iter_init (&attributes_iter, attributes); + while (g_hash_table_iter_next (&attributes_iter, &attr_key, &attr_value)) { + _accumulate_string("[", &attribute_accumulator); + _accumulate_string((char*)attr_key, &attribute_accumulator); + _accumulate_string("=", &attribute_accumulator); + _accumulate_string((char*)attr_value, &attribute_accumulator); + _accumulate_string("]", &attribute_accumulator); + } + g_hash_table_unref(attributes); + } + + char result[SAFE_BUFFER_SIZE + 1]; + snprintf(result, SAFE_BUFFER_SIZE, "[[%s],[%s],[%d,%d],[%s],[%s]]\n", node_role_name, attribute_accumulator.string, node_width, node_height, node_name, state_accumulator.string); + + free(node_name); + free(node_role_name); + + if (state_accumulator.string) + g_free(state_accumulator.string); + + if (attribute_accumulator.string) + g_free(attribute_accumulator.string); + + if (component) + g_object_unref(component); + + if (extent) + g_free(extent); + + if (node_state_set) + g_object_unref(node_state_set); + + return strdup(result); +} + +static void test_atspi_parent_child_relation(AtspiAccessible *obj, AtspiAccessible *parent_candidate, int parent_candidate_index) +{ + int parent_index = atspi_accessible_get_index_in_parent(obj, NULL); + AtspiAccessible *parent = atspi_accessible_get_parent(obj, NULL); + if (parent_index != parent_candidate_index || parent_candidate != parent) { + printf("[FAIL<%d,", parent_candidate_index); + + if (parent == NULL) + printf("_"); + else + printf("%d", parent_index); + + printf(">]\t"); + + } else { + printf("[OK]\t"); + } +} + +static int expand_r(int indent_number, AtspiAccessible *object, bool check_integrity) +{ + char *indent = multiply_string(' ', indent_number*indent_width); + if (indent != NULL) { + printf("%s", indent); + free(indent); + } + + char *node_info = get_info(object); + if (node_info != NULL) { + printf("%s", node_info); + free(node_info); + } + + int count = atspi_accessible_get_child_count(object, NULL); + for (int i = 0; i < count; i++) { + AtspiAccessible *child = atspi_accessible_get_child_at_index(object, i, NULL); + if (child) { + if (check_integrity) + test_atspi_parent_child_relation(child, object, i); + + expand_r(indent_number + 1, child, check_integrity); + } + } + return 0; +} + +void print_help() +{ + printf("AT-SPI2-CORE-UTIL\n\n"); + printf("USAGE: at_spi2_tool [OPTION] [PARAMETER] ...\n\n"); + printf("OPTION LIST:\n"); + printf("-h, --help\t\tshow this message\n"); + printf("-g, --show-legend\tprint AT-SPI state legend\n"); + printf("-l, --list-apps\t\tlist all applications of desktop\n"); + printf("-d, --tree-dump\t\tdump tree for selected application\n"); + printf("-c, --tree-check\tcheck tree for selected application\n"); + printf("-i, --indent\t\tset indentation size\n"); + printf("\nEXAMPLE:\n"); + printf("\tat_spi2_tool -i3 -d quickpanel\n"); + printf("\t show AT-SPI tree for node \"quickpanel\" using three-space indentation\n"); + 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"); +} + +static void atspi_tree_traverse(AtspiAccessible *desktop, const char *app_name, bool dump, bool check) +{ + int count = atspi_accessible_get_child_count(desktop, NULL); + for (int i = 0; i < count; i++) { + AtspiAccessible *child = atspi_accessible_get_child_at_index(desktop, i, NULL); + if (child) { + char *name = atspi_accessible_get_name(child, NULL); + + if (!dump && !check) + printf("%s\n", name); + + if (dump && name && !strcmp(name, app_name)) { + expand_r(0, child, false); + break; + } + + if (check && name && !strcmp(name, app_name)) { + test_atspi_parent_child_relation(child, desktop, i); + expand_r(0, child, true); + break; + } + } + } +} + +static void run_command(int argc, char *argv[], AtspiAccessible *desktop) +{ + struct option long_options[] = { + {"help", no_argument, 0, 'h'}, + {"show-legend", no_argument, 0, 'g'}, + {"list-apps", no_argument, 0, 'l'}, + {"tree-dump", required_argument, 0, 'd'}, + {"tree-check", required_argument, 0, 'c'}, + {"indent", required_argument, 0, 'i'}, + }; + + int command = 0; + int option_index = 0; + + while (TRUE) { + command = getopt_long(argc, argv, "hgld:c:i:", long_options, &option_index); + + if (command == ERROR_STATE) + break; + + switch (command) { + case 'h': + print_help(); + break; + + case 'g': + _print_atspi_states_legend(); + break; + + case 'l': + atspi_tree_traverse(desktop, NULL, false, false); + break; + + case 'd': + atspi_tree_traverse(desktop, optarg, true, false); + break; + + case 'c': + atspi_tree_traverse(desktop, optarg, false, true); + break; + + case 'i': + set_indent(atoi(optarg)); + break; + + case '?': + break; + + default: + abort(); + } + } +} + +int main(int argc, char *argv[]) +{ + if (argc < 2) { + printf("Arguments required. Type %s --help.\n", argv[0]); + return -1; + } + + AtspiAccessible *desktop = atspi_get_desktop(0); + + if (!desktop) { + fprintf(stderr, "atspi_get_desktop failed\n"); + return 1; + } + + atspi_init(); + + run_command(argc, argv, desktop); + + return 0; +} -- 2.7.4 From 9ace85989ebf7ac08fd6bf091d18132180ff8dc3 Mon Sep 17 00:00:00 2001 From: Lukasz Wlazly Date: Tue, 27 Sep 2016 14:08:24 +0200 Subject: [PATCH 10/16] Tool for checking AT-SPI tree integrity v0.95 Code has been refactored and some additional features have appeared Change-Id: I4ff2a96f550df3d52116d166e079cc01d4a8b4b1 --- test/Makefile.am | 8 +- test/at_spi2_tool.c | 357 +++++++++++++++++++++++++++++++++++----------------- 2 files changed, 252 insertions(+), 113 deletions(-) diff --git a/test/Makefile.am b/test/Makefile.am index f233c36..6725315 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,10 +1,16 @@ LDADD = $(top_builddir)/atspi/libatspi.la + bin_PROGRAMS = at_spi2_tool at_spi2_tool_SOURCES = at_spi2_tool.c at_spi2_tool_CPPFLAGS = -I$(top_srcdir) -I$(top_builddir) -I$(top_builddir)/atspi -at_spi2_tool_CFLAGS = $(GLIB_CFLAGS) --std=c99 $(GOBJ_LIBS) $(DBUS_CFLAGS) +at_spi2_tool_CFLAGS = $(GLIB_CFLAGS) --std=c99 -Wall $(GOBJ_LIBS) $(DBUS_CFLAGS) at_spi2_tool_LDFLAGS = +noinst_PROGRAMS = memory +memory_SOURCES = memory.c +memory_CPPFLAGS = -I$(top_srcdir) -I$(top_builddir) -I$(top_builddir)/atspi +memory_CFLAGS = $(GLIB_CFLAGS) $(GOBJ_LIBS) $(DBUS_CFLAGS) +memory_LDFLAGS = -include $(top_srcdir)/git.mk diff --git a/test/at_spi2_tool.c b/test/at_spi2_tool.c index f67700d..252f3e5 100644 --- a/test/at_spi2_tool.c +++ b/test/at_spi2_tool.c @@ -7,10 +7,19 @@ #define ERROR_STATE -1 #define SAFE_BUFFER_SIZE 255 +#define CHECK_OUTPUT_WIDTH 15 +#define MINIMAL_MODULE_WIDTH 3 +#define ATTR_WIDTH 50 +#define NUMBER_WIDTH 6 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #define COLUMN_NO 3 +#define FLAG_NO 3 +#define DUMP 0 +#define CHECK 1 +#define FIRST_MATCH 2 static unsigned indent_width = 2; +static int module_name_limit = -1; static const char* atspi_state_names[] = { [ATSPI_STATE_INVALID] = "INVALID", @@ -62,17 +71,19 @@ static const char* atspi_state_names[] = { [ATSPI_STATE_LAST_DEFINED] = "LAST_DEFINED" }; -typedef struct _StringAccumulator { - char *string; - int length; -} StringAccumulator; +typedef struct _Box_Size { + int height; + int width; +} Box_Size; -char *strdup(const char *c) { +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) { +static char *_multiply_string(char c, unsigned number) +{ char *result = (char *)calloc(1, number + 1); if (result == NULL) @@ -83,21 +94,39 @@ static char *multiply_string(char c, unsigned number) { return result; } -static void _print_atspi_states_legend() { +static void _print_module_legend() +{ + printf("\n[[node role name],[attributes list],[width,height],[node name],[states list]]\n\n"); +} + +static void _print_atspi_states_legend() +{ + _print_module_legend(); + int array_len = ARRAY_SIZE(atspi_state_names); int line_count = (array_len + COLUMN_NO - 1)/COLUMN_NO; for (int line_idx = 0; line_idx < line_count; line_idx++) { - if ((line_idx < line_count - 1) || (array_len % 3 == 0)) { - printf("[%d]\t%-24s[%d]\t%-24s[%d]\t%s\n", line_idx * 3, atspi_state_names[line_idx * 3], (line_idx * 3) + 1, atspi_state_names[(line_idx * 3) + 1], (line_idx * 3) + 2, atspi_state_names[(line_idx * 3) + 2]); - } else if (array_len % 3 == 2) { - printf("[%d]\t%-24s[%d]\t%s\n", line_idx * 3, atspi_state_names[line_idx * 3], (line_idx * 3) + 1, atspi_state_names[(line_idx * 3) + 1]); + if ((line_idx < line_count - 1) || (array_len % COLUMN_NO == 0)) { + printf("[%d]\t%-24s[%d]\t%-24s[%d]\t%s\n", + line_idx * COLUMN_NO, + atspi_state_names[line_idx * COLUMN_NO], + (line_idx * COLUMN_NO) + 1, + atspi_state_names[(line_idx * COLUMN_NO) + 1], + (line_idx * COLUMN_NO) + 2, + atspi_state_names[(line_idx * COLUMN_NO) + 2]); + } else if (array_len % COLUMN_NO == 2) { + printf("[%d]\t%-24s[%d]\t%s\n", + line_idx * COLUMN_NO, + atspi_state_names[line_idx * COLUMN_NO], + (line_idx * COLUMN_NO) + 1, + atspi_state_names[(line_idx * COLUMN_NO) + 1]); } else { - printf("[%d]\t%s\n", line_idx * 3, atspi_state_names[line_idx * 3]); + printf("[%d]\t%s\n", line_idx * COLUMN_NO, atspi_state_names[line_idx * COLUMN_NO]); } } } -static void set_indent(int indent_size) +static void _set_indent(int indent_size) { if (indent_size < 0) { fprintf(stderr, "WARNING: Invalid indent size. Default value retained.\n"); @@ -107,6 +136,16 @@ static void set_indent(int indent_size) indent_width = indent_size; } +static void _set_module_length_limit(int limit) +{ + if (limit < MINIMAL_MODULE_WIDTH) { + fprintf(stderr, "WARNING: Invalid maximum field size. Default value retained.\n"); + return; + } + + module_name_limit = limit; +} + static int _int_sort_function(gconstpointer a, gconstpointer b) { int int_a = GPOINTER_TO_INT (a); @@ -115,129 +154,187 @@ static int _int_sort_function(gconstpointer a, gconstpointer b) return int_a - int_b; } -static int _accumulate_string(const char *string, StringAccumulator *accumulator) { - if (!accumulator) - return FALSE; - - if (string) { - int length = accumulator->length + strlen(string); - char *rebuffer = realloc(accumulator->string, length + 1); - if (rebuffer) { - strcpy(rebuffer + accumulator->length, string); - accumulator->string = rebuffer; - accumulator->length = length; - } else { - return FALSE; - } +static void _truncate_string(char *string, int length_limit) +{ + if (length_limit < MINIMAL_MODULE_WIDTH || !string) + return; + + int len = strlen(string); + + if (len > length_limit) + memcpy(string + length_limit - 3, "...", 4); +} + +static size_t _combine_strings(char **destination, const char *source) +{ + if (!source || !*source || !destination) + return 0; + + size_t old_len = *destination ? strlen(*destination) : 0; + size_t source_len = strlen(source); + size_t len = old_len + source_len; + char *buf = realloc(*destination, (len + 1) * sizeof(char)); + + if (!buf) { + fprintf(stderr, "_combine_strings: allocation failed"); + return old_len; } - return TRUE; + + memcpy(buf + old_len, source, source_len + 1); + + *destination = buf; + + return len; } -static char *get_info(AtspiAccessible *node) { - if (!node) +static Box_Size *_get_box_size(AtspiAccessible *node) +{ + Box_Size *box_size = (Box_Size *)malloc(sizeof(Box_Size)); + if (box_size == NULL) return NULL; - int node_width = -1; - int node_height = -1; - char *node_name = atspi_accessible_get_name(node, NULL); - char *node_role_name = atspi_accessible_get_role_name(node, NULL); + box_size->width = -1; + box_size->height = -1; + AtspiComponent *component = atspi_accessible_get_component_iface(node); - AtspiRect *extent = NULL; - if (component != NULL){ - extent = atspi_component_get_extents(component, ATSPI_COORD_TYPE_SCREEN, NULL); + if (component == NULL) + return box_size; - if (extent != NULL) { - node_width = extent->width; - node_height = extent->height; - } - } + AtspiRect *extent = atspi_component_get_extents(component, ATSPI_COORD_TYPE_SCREEN, NULL); + if (extent == NULL) + return box_size; + + box_size->width = extent->width; + box_size->height = extent->height; + + g_object_unref(component); + g_free(extent); + return box_size; +} + +static char *_get_states(AtspiAccessible *node) +{ AtspiStateSet *node_state_set = atspi_accessible_get_state_set(node); GArray *states = atspi_state_set_get_states(node_state_set); g_array_sort(states, _int_sort_function); - AtspiStateType state; - StringAccumulator state_accumulator = {}; + AtspiStateType state_type; + char *state_string = NULL; + for (int i = 0; states && (i < states->len); i++) { - state = g_array_index(states, AtspiStateType, i); + state_type = g_array_index(states, AtspiStateType, i); + char node_state_str[8]; - sprintf(node_state_str, "[%d]", state); - _accumulate_string(node_state_str, &state_accumulator); + sprintf(node_state_str, "(%d)", state_type); + _combine_strings(&state_string, node_state_str); } + g_array_free(states, 0); + g_object_unref(node_state_set); + + return state_string; +} - StringAccumulator attribute_accumulator = {}; +static char *_get_attributes(AtspiAccessible *node) +{ GHashTable *attributes = NULL; attributes = atspi_accessible_get_attributes(node, NULL); - if (attributes) { - GHashTableIter attributes_iter; - gpointer attr_key, attr_value; - g_hash_table_iter_init (&attributes_iter, attributes); - while (g_hash_table_iter_next (&attributes_iter, &attr_key, &attr_value)) { - _accumulate_string("[", &attribute_accumulator); - _accumulate_string((char*)attr_key, &attribute_accumulator); - _accumulate_string("=", &attribute_accumulator); - _accumulate_string((char*)attr_value, &attribute_accumulator); - _accumulate_string("]", &attribute_accumulator); - } - g_hash_table_unref(attributes); - } - char result[SAFE_BUFFER_SIZE + 1]; - snprintf(result, SAFE_BUFFER_SIZE, "[[%s],[%s],[%d,%d],[%s],[%s]]\n", node_role_name, attribute_accumulator.string, node_width, node_height, node_name, state_accumulator.string); + if (!attributes) + return NULL; - free(node_name); - free(node_role_name); + GHashTableIter attributes_iter; + gpointer attr_key; + gpointer attr_value; + g_hash_table_iter_init (&attributes_iter, attributes); + char *result = NULL; + while (g_hash_table_iter_next (&attributes_iter, &attr_key, &attr_value)) { + char attributes_string[ATTR_WIDTH]; + int ret = snprintf(attributes_string, ATTR_WIDTH, "(%s=%s)", (char*)attr_key, (char*)attr_value); + if (ret >= ATTR_WIDTH) { + fprintf(stderr, "_get_attributes: generated string is too long. Buffer overflow"); + abort(); + } + _combine_strings(&result, attributes_string); + } + g_hash_table_unref(attributes); - if (state_accumulator.string) - g_free(state_accumulator.string); + return result; +} - if (attribute_accumulator.string) - g_free(attribute_accumulator.string); +static char *_get_info(AtspiAccessible *node, int length_limit) +{ + if (!node) + return NULL; - if (component) - g_object_unref(component); + char *node_name = atspi_accessible_get_name(node, NULL); + char *node_role_name = atspi_accessible_get_role_name(node, NULL); - if (extent) - g_free(extent); + char *attributes = _get_attributes(node); + _truncate_string(attributes, length_limit); + Box_Size *box_size = _get_box_size(node); + char *states = _get_states(node); + _truncate_string(states, length_limit); + + char result[SAFE_BUFFER_SIZE]; + int ret = snprintf(result, SAFE_BUFFER_SIZE, "[[%s],[%s],[%d,%d],[%s],[%s]]", + node_role_name, + attributes, + box_size->width, + box_size->height, + node_name, + states); + + if (ret >= SAFE_BUFFER_SIZE) { + fprintf(stderr, "_get_info: generated string is too long. Buffer overflow"); + abort(); + } - if (node_state_set) - g_object_unref(node_state_set); + free(node_name); + free(node_role_name); + free(attributes); + free(box_size); + free(states); - return strdup(result); + return _strdup(result); } -static void test_atspi_parent_child_relation(AtspiAccessible *obj, AtspiAccessible *parent_candidate, int parent_candidate_index) +static void _test_atspi_parent_child_relation(AtspiAccessible *obj, AtspiAccessible *parent_candidate, int parent_candidate_index) { int parent_index = atspi_accessible_get_index_in_parent(obj, NULL); AtspiAccessible *parent = atspi_accessible_get_parent(obj, NULL); + + char output[CHECK_OUTPUT_WIDTH]; if (parent_index != parent_candidate_index || parent_candidate != parent) { - printf("[FAIL<%d,", parent_candidate_index); + char parent_status[NUMBER_WIDTH]; if (parent == NULL) - printf("_"); + strcpy(parent_status, "_"); else - printf("%d", parent_index); + snprintf(parent_status, NUMBER_WIDTH, "%d", parent_index); - printf(">]\t"); + snprintf(output, CHECK_OUTPUT_WIDTH, "[FAIL<%d,%s>]", parent_candidate_index, parent_status); } else { - printf("[OK]\t"); + snprintf(output, CHECK_OUTPUT_WIDTH, "[OK]"); } + + printf("%-*s\t", CHECK_OUTPUT_WIDTH, output); } -static int expand_r(int indent_number, AtspiAccessible *object, bool check_integrity) +static int _print_atspi_tree_verify_maybe_r(int indent_number, AtspiAccessible *object, bool check_integrity, int length_limit) { - char *indent = multiply_string(' ', indent_number*indent_width); + char *indent = _multiply_string(' ', indent_number*indent_width); if (indent != NULL) { printf("%s", indent); free(indent); } - char *node_info = get_info(object); + char *node_info = _get_info(object, length_limit); if (node_info != NULL) { - printf("%s", node_info); + printf("%s\n", node_info); free(node_info); } @@ -246,15 +343,15 @@ static int expand_r(int indent_number, AtspiAccessible *object, bool check_integ AtspiAccessible *child = atspi_accessible_get_child_at_index(object, i, NULL); if (child) { if (check_integrity) - test_atspi_parent_child_relation(child, object, i); + _test_atspi_parent_child_relation(child, object, i); - expand_r(indent_number + 1, child, check_integrity); + _print_atspi_tree_verify_maybe_r(indent_number + 1, child, check_integrity, length_limit); } } return 0; } -void print_help() +void _print_help() { printf("AT-SPI2-CORE-UTIL\n\n"); printf("USAGE: at_spi2_tool [OPTION] [PARAMETER] ...\n\n"); @@ -264,7 +361,9 @@ void print_help() printf("-l, --list-apps\t\tlist all applications of desktop\n"); printf("-d, --tree-dump\t\tdump tree for selected application\n"); printf("-c, --tree-check\tcheck tree for selected application\n"); - printf("-i, --indent\t\tset indentation size\n"); + printf("-f, --first-match\tperform dump or check only for first matching application\n"); + printf("-i, --indent\t\tset indentation size, default value stands at 2\n"); + printf("-t, --truncate\t\tset maximum single field size, default value stands at 30\n"); printf("\nEXAMPLE:\n"); printf("\tat_spi2_tool -i3 -d quickpanel\n"); printf("\t show AT-SPI tree for node \"quickpanel\" using three-space indentation\n"); @@ -272,32 +371,44 @@ void print_help() printf("\t show AT-SPI tree with integrity test for node \"starter\" using one-space indentation\n"); } -static void atspi_tree_traverse(AtspiAccessible *desktop, const char *app_name, bool dump, bool check) +static void _atspi_tree_traverse(AtspiAccessible *desktop, const char *app_name, bool dump, bool check, bool first_match, int length_limit) { int count = atspi_accessible_get_child_count(desktop, NULL); + bool app_name_matched = false; for (int i = 0; i < count; i++) { AtspiAccessible *child = atspi_accessible_get_child_at_index(desktop, i, NULL); if (child) { char *name = atspi_accessible_get_name(child, NULL); - if (!dump && !check) + if (!dump && !check) { printf("%s\n", name); - - if (dump && name && !strcmp(name, app_name)) { - expand_r(0, child, false); - break; } - if (check && name && !strcmp(name, app_name)) { - test_atspi_parent_child_relation(child, desktop, i); - expand_r(0, child, true); - break; + if ((check || dump) && name && !strcmp(name, app_name)) { + app_name_matched = true; + + _print_module_legend(); + + if (check) + _test_atspi_parent_child_relation(child, desktop, i); + + _print_atspi_tree_verify_maybe_r(0, child, check, length_limit); + + if (first_match) { + free(name); + break; + } else + printf("\n"); } + free(name); } } + + if (!app_name_matched && (dump || check)) + fprintf(stderr, "There is no application with name: %s. Try again.\n", app_name); } -static void run_command(int argc, char *argv[], AtspiAccessible *desktop) +static void _run_command(int argc, char *argv[], AtspiAccessible *desktop) { struct option long_options[] = { {"help", no_argument, 0, 'h'}, @@ -305,21 +416,25 @@ static void run_command(int argc, char *argv[], AtspiAccessible *desktop) {"list-apps", no_argument, 0, 'l'}, {"tree-dump", required_argument, 0, 'd'}, {"tree-check", required_argument, 0, 'c'}, + {"first-match", no_argument, 0, 'f'}, {"indent", required_argument, 0, 'i'}, + {"truncate", required_argument, 0, 't'}, }; int command = 0; int option_index = 0; + bool traverse_flags[FLAG_NO] = {false}; + char *app_name = NULL; while (TRUE) { - command = getopt_long(argc, argv, "hgld:c:i:", long_options, &option_index); + command = getopt_long(argc, argv, "hgld:c:ft:i:", long_options, &option_index); if (command == ERROR_STATE) break; switch (command) { case 'h': - print_help(); + _print_help(); break; case 'g': @@ -327,28 +442,42 @@ static void run_command(int argc, char *argv[], AtspiAccessible *desktop) break; case 'l': - atspi_tree_traverse(desktop, NULL, false, false); + _atspi_tree_traverse(desktop, NULL, false, false, false, module_name_limit); break; case 'd': - atspi_tree_traverse(desktop, optarg, true, false); + traverse_flags[DUMP] = true; + app_name = optarg; break; case 'c': - atspi_tree_traverse(desktop, optarg, false, true); + traverse_flags[CHECK] = true; + app_name = optarg; + break; + + case 'f': + traverse_flags[FIRST_MATCH] = true; break; case 'i': - set_indent(atoi(optarg)); + _set_indent(atoi(optarg)); + break; + + case 't': + _set_module_length_limit(atoi(optarg)); break; case '?': + fprintf(stderr, "Invalid parameter. Use: \"--help\"\n"); break; default: abort(); } } + + if (traverse_flags[DUMP] || traverse_flags[CHECK]) + _atspi_tree_traverse(desktop, app_name, traverse_flags[DUMP], traverse_flags[CHECK], traverse_flags[FIRST_MATCH], module_name_limit); } int main(int argc, char *argv[]) @@ -358,16 +487,20 @@ int main(int argc, char *argv[]) return -1; } - AtspiAccessible *desktop = atspi_get_desktop(0); + int result = atspi_init(); + if (result != 0) + { + fprintf(stderr, "Unable to initilize AT-SPI infrastructure, atspi_init failed\n"); + return -1; + } + AtspiAccessible *desktop = atspi_get_desktop(0); if (!desktop) { fprintf(stderr, "atspi_get_desktop failed\n"); - return 1; + return -1; } - atspi_init(); - - run_command(argc, argv, desktop); + _run_command(argc, argv, desktop); return 0; } -- 2.7.4 From b82529fc524ce440a1b7b034361f37aee8b1664d Mon Sep 17 00:00:00 2001 From: Lukasz Wlazly Date: Thu, 6 Oct 2016 16:20:46 +0200 Subject: [PATCH 11/16] Tool for checking AT-SPI tree integrity v1.0 now, in case of fail, except nodes' indexes pointers are also printed Change-Id: I8823fbad9243c1969ed81f35ef6968858846fed2 --- test/at_spi2_tool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/at_spi2_tool.c b/test/at_spi2_tool.c index 252f3e5..a520412 100644 --- a/test/at_spi2_tool.c +++ b/test/at_spi2_tool.c @@ -7,7 +7,7 @@ #define ERROR_STATE -1 #define SAFE_BUFFER_SIZE 255 -#define CHECK_OUTPUT_WIDTH 15 +#define CHECK_OUTPUT_WIDTH 38 #define MINIMAL_MODULE_WIDTH 3 #define ATTR_WIDTH 50 #define NUMBER_WIDTH 6 @@ -315,7 +315,7 @@ static void _test_atspi_parent_child_relation(AtspiAccessible *obj, AtspiAccessi else snprintf(parent_status, NUMBER_WIDTH, "%d", parent_index); - snprintf(output, CHECK_OUTPUT_WIDTH, "[FAIL<%d,%s>]", parent_candidate_index, parent_status); + snprintf(output, CHECK_OUTPUT_WIDTH, "[FAIL<%d,%s><%p,%p>]", parent_candidate_index, parent_status, parent_candidate, parent); } else { snprintf(output, CHECK_OUTPUT_WIDTH, "[OK]"); -- 2.7.4 From 3d23188a026eafde59f85e70f9ead9d830f67a21 Mon Sep 17 00:00:00 2001 From: Lukasz Wlazly Date: Thu, 6 Oct 2016 16:52:59 +0200 Subject: [PATCH 12/16] Tool for checking AT-SPI tree integrity v1.01 Only one macro redefined Change-Id: I5e85f455e6f1a5ae89d8dddd3d352488b5a1122e --- test/at_spi2_tool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/at_spi2_tool.c b/test/at_spi2_tool.c index a520412..8c6bc6f 100644 --- a/test/at_spi2_tool.c +++ b/test/at_spi2_tool.c @@ -7,7 +7,7 @@ #define ERROR_STATE -1 #define SAFE_BUFFER_SIZE 255 -#define CHECK_OUTPUT_WIDTH 38 +#define CHECK_OUTPUT_WIDTH 42 #define MINIMAL_MODULE_WIDTH 3 #define ATTR_WIDTH 50 #define NUMBER_WIDTH 6 -- 2.7.4 From af2668010904f4be11e42b3683b9129ababc1d4c Mon Sep 17 00:00:00 2001 From: Lukasz Wlazly Date: Wed, 12 Oct 2016 15:28:33 +0200 Subject: [PATCH 13/16] Tool for checking tree integrity v1.02 Change-Id: I1fe9ca1f3eaf7af2325d3248cacaa8cabc6d14cd --- test/at_spi2_tool.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/test/at_spi2_tool.c b/test/at_spi2_tool.c index 8c6bc6f..1a951da 100644 --- a/test/at_spi2_tool.c +++ b/test/at_spi2_tool.c @@ -17,6 +17,7 @@ #define DUMP 0 #define CHECK 1 #define FIRST_MATCH 2 +#define VERSION "1.02" static unsigned indent_width = 2; static int module_name_limit = -1; @@ -357,6 +358,7 @@ void _print_help() printf("USAGE: at_spi2_tool [OPTION] [PARAMETER] ...\n\n"); printf("OPTION LIST:\n"); printf("-h, --help\t\tshow this message\n"); + printf("-v, --version\t\tshow actual version of tool\n"); printf("-g, --show-legend\tprint AT-SPI state legend\n"); printf("-l, --list-apps\t\tlist all applications of desktop\n"); printf("-d, --tree-dump\t\tdump tree for selected application\n"); @@ -370,6 +372,10 @@ 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 _atspi_tree_traverse(AtspiAccessible *desktop, const char *app_name, bool dump, bool check, bool first_match, int length_limit) { @@ -412,6 +418,7 @@ static void _run_command(int argc, char *argv[], AtspiAccessible *desktop) { struct option long_options[] = { {"help", no_argument, 0, 'h'}, + {"version", no_argument, 0, 'v'}, {"show-legend", no_argument, 0, 'g'}, {"list-apps", no_argument, 0, 'l'}, {"tree-dump", required_argument, 0, 'd'}, @@ -427,7 +434,7 @@ static void _run_command(int argc, char *argv[], AtspiAccessible *desktop) char *app_name = NULL; while (TRUE) { - command = getopt_long(argc, argv, "hgld:c:ft:i:", long_options, &option_index); + command = getopt_long(argc, argv, "hvgld:c:ft:i:", long_options, &option_index); if (command == ERROR_STATE) break; @@ -437,6 +444,10 @@ static void _run_command(int argc, char *argv[], AtspiAccessible *desktop) _print_help(); break; + case 'v': + _print_version(); + break; + case 'g': _print_atspi_states_legend(); break; -- 2.7.4 From 960f8b5d524b9145c9230ad1ce99a46920091aee Mon Sep 17 00:00:00 2001 From: Lukasz Wlazly Date: Fri, 14 Oct 2016 13:35:57 +0200 Subject: [PATCH 14/16] Tool for checking AT-SPI tree integrity v1.1 Change-Id: Id46b609f80f36b93bb7af938937e4893d51ac1d7 --- test/at_spi2_tool.c | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/test/at_spi2_tool.c b/test/at_spi2_tool.c index 1a951da..b47d432 100644 --- a/test/at_spi2_tool.c +++ b/test/at_spi2_tool.c @@ -17,7 +17,7 @@ #define DUMP 0 #define CHECK 1 #define FIRST_MATCH 2 -#define VERSION "1.02" +#define VERSION "1.1" static unsigned indent_width = 2; static int module_name_limit = -1; @@ -73,8 +73,8 @@ static const char* atspi_state_names[] = { }; typedef struct _Box_Size { - int height; - int width; + char *height; + char *width; } Box_Size; char *_strdup(const char *c) @@ -194,8 +194,14 @@ static Box_Size *_get_box_size(AtspiAccessible *node) if (box_size == NULL) return NULL; - box_size->width = -1; - box_size->height = -1; + char *width = NULL; + char *height = NULL; + + _combine_strings(&width, "_"); + _combine_strings(&height, "_"); + + box_size->width = width; + box_size->height = height; AtspiComponent *component = atspi_accessible_get_component_iface(node); @@ -206,12 +212,23 @@ static Box_Size *_get_box_size(AtspiAccessible *node) if (extent == NULL) return box_size; - box_size->width = extent->width; - box_size->height = extent->height; + *width = '\0'; + *height = '\0'; + + char temp_buff[NUMBER_WIDTH]; + + snprintf(temp_buff, NUMBER_WIDTH, "%d", extent->width); + _combine_strings(&width, temp_buff); + + snprintf(temp_buff, NUMBER_WIDTH, "%d", extent->height); + _combine_strings(&height, temp_buff); g_object_unref(component); g_free(extent); + box_size->width = width; + box_size->height = height; + return box_size; } @@ -280,7 +297,7 @@ static char *_get_info(AtspiAccessible *node, int length_limit) _truncate_string(states, length_limit); char result[SAFE_BUFFER_SIZE]; - int ret = snprintf(result, SAFE_BUFFER_SIZE, "[[%s],[%s],[%d,%d],[%s],[%s]]", + int ret = snprintf(result, SAFE_BUFFER_SIZE, "[[%s],[%s],[%s,%s],[%s],[%s]]", node_role_name, attributes, box_size->width, @@ -296,7 +313,11 @@ static char *_get_info(AtspiAccessible *node, int length_limit) free(node_name); free(node_role_name); free(attributes); - free(box_size); + if (box_size) { + free(box_size->width); + free(box_size->height); + free(box_size); + } free(states); return _strdup(result); -- 2.7.4 From d0a4acf13e4c7cc27b6de6d3f3280eb8b7cd9a4f Mon Sep 17 00:00:00 2001 From: Shinwoo Kim Date: Sat, 12 Nov 2016 15:00:05 +0900 Subject: [PATCH 15/16] Build DEBUG package Change-Id: Id6ce145487550d1a5cca2e7c893b1cd4e8b59793 --- packaging/at-spi2-core.spec | 3 --- 1 file changed, 3 deletions(-) diff --git a/packaging/at-spi2-core.spec b/packaging/at-spi2-core.spec index 472f089..bdb6b7c 100644 --- a/packaging/at-spi2-core.spec +++ b/packaging/at-spi2-core.spec @@ -1,4 +1,3 @@ -%define debug_package %{nil} %bcond_with x Name: at-spi2-core @@ -86,8 +85,6 @@ find %{buildroot} -name '*.la' -or -name '*.a' | xargs rm -f %make_install %find_lang %{name} -%check - %clean rm -fr %{buildroot} -- 2.7.4 From 4b958d41a4fc158c4fa73b8fdefb295fd74799ce Mon Sep 17 00:00:00 2001 From: Shinwoo Kim Date: Sat, 12 Nov 2016 15:01:18 +0900 Subject: [PATCH 16/16] [at_spi2_tool] report x, y information of accessible object Change-Id: Ibcfab40ef65f91617303e86c4fb1b5275de89be7 --- test/at_spi2_tool.c | 52 +++++++++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/test/at_spi2_tool.c b/test/at_spi2_tool.c index b47d432..7a7b9a5 100644 --- a/test/at_spi2_tool.c +++ b/test/at_spi2_tool.c @@ -73,6 +73,8 @@ static const char* atspi_state_names[] = { }; typedef struct _Box_Size { + char *x; + char *y; char *height; char *width; } Box_Size; @@ -97,7 +99,7 @@ static char *_multiply_string(char c, unsigned number) static void _print_module_legend() { - printf("\n[[node role name],[attributes list],[width,height],[node name],[states list]]\n\n"); + printf("\n[[node role name],[attributes list],[x,y,width,height],[node name],[states list]]\n\n"); } static void _print_atspi_states_legend() @@ -194,38 +196,40 @@ static Box_Size *_get_box_size(AtspiAccessible *node) if (box_size == NULL) return NULL; + char *x = NULL; + char *y = NULL; char *width = NULL; char *height = NULL; - _combine_strings(&width, "_"); - _combine_strings(&height, "_"); - - box_size->width = width; - box_size->height = height; - AtspiComponent *component = atspi_accessible_get_component_iface(node); + AtspiRect *extent = component ? atspi_component_get_extents(component, ATSPI_COORD_TYPE_SCREEN, NULL) : NULL; - if (component == NULL) - return box_size; - - AtspiRect *extent = atspi_component_get_extents(component, ATSPI_COORD_TYPE_SCREEN, NULL); - if (extent == NULL) - return box_size; + if (extent == NULL) { + _combine_strings(&x, "_"); + _combine_strings(&y, "_"); + _combine_strings(&width, "_"); + _combine_strings(&height, "_"); + } else { + char temp_buff[NUMBER_WIDTH]; - *width = '\0'; - *height = '\0'; + snprintf(temp_buff, NUMBER_WIDTH, "%d", extent->x); + _combine_strings(&x, temp_buff); - char temp_buff[NUMBER_WIDTH]; + snprintf(temp_buff, NUMBER_WIDTH, "%d", extent->y); + _combine_strings(&y, temp_buff); - snprintf(temp_buff, NUMBER_WIDTH, "%d", extent->width); - _combine_strings(&width, temp_buff); + snprintf(temp_buff, NUMBER_WIDTH, "%d", extent->width); + _combine_strings(&width, temp_buff); - snprintf(temp_buff, NUMBER_WIDTH, "%d", extent->height); - _combine_strings(&height, temp_buff); + snprintf(temp_buff, NUMBER_WIDTH, "%d", extent->height); + _combine_strings(&height, temp_buff); - g_object_unref(component); - g_free(extent); + g_object_unref(component); + g_free(extent); + } + box_size->x = x; + box_size->y = y; box_size->width = width; box_size->height = height; @@ -297,9 +301,11 @@ static char *_get_info(AtspiAccessible *node, int length_limit) _truncate_string(states, length_limit); char result[SAFE_BUFFER_SIZE]; - int ret = snprintf(result, SAFE_BUFFER_SIZE, "[[%s],[%s],[%s,%s],[%s],[%s]]", + int ret = snprintf(result, SAFE_BUFFER_SIZE, "[[%s],[%s],[%s,%s,%s,%s],[%s],[%s]]", node_role_name, attributes, + box_size->x, + box_size->y, box_size->width, box_size->height, node_name, -- 2.7.4