From: Mark Doffman Date: Wed, 7 Oct 2009 13:52:13 +0000 (+0100) Subject: 2009-07-10 Mark Doffman X-Git-Tag: AT_SPI2_ATK_2_12_0~484 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fat-spi2-atk.git;a=commitdiff_plain;h=32cb1ad2109d1c1d408c56e23949c601f3cce3f8 2009-07-10 Mark Doffman Re-add the cspi tests. Add desktop file so that the ATK bridge GTK modules environment variable is set properly by Gnome-session. Add library flags, compile error on Sun station. Fix provided by: Willie Walker --- diff --git a/Makefile.am b/Makefile.am index 131502a..c3bb9f9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1 +1 @@ -SUBDIRS=common atk-adaptor cspi +SUBDIRS=common atk-adaptor cspi tests diff --git a/atk-adaptor/Makefile.am b/atk-adaptor/Makefile.am index 23438b3..129f491 100644 --- a/atk-adaptor/Makefile.am +++ b/atk-adaptor/Makefile.am @@ -1,25 +1,25 @@ gtkmoduledir = $(libdir)/$(GTK_MODULE_DIR) -gtkmodule_LTLIBRARIES = libspiatk.la +gtkmodule_LTLIBRARIES = libatk-bridge.la -libspiatk_la_CFLAGS = $(DBUS_GLIB_CFLAGS) \ - $(ATK_CFLAGS) \ - $(DBIND_CFLAGS) \ - $(DROUTE_CFLAGS) \ - -I$(top_srcdir) \ - -DATSPI_INTROSPECTION_PATH=\"$(pkgdatadir)/$(DEFAULT_ATSPI_INTROSPECTION_PATH)\" +libatk_bridge_la_CFLAGS = $(DBUS_GLIB_CFLAGS) \ + $(ATK_CFLAGS) \ + $(DBIND_CFLAGS) \ + $(DROUTE_CFLAGS) \ + -I$(top_srcdir) \ + -DATSPI_INTROSPECTION_PATH=\"$(pkgdatadir)/$(DEFAULT_ATSPI_INTROSPECTION_PATH)\" -libspiatk_la_LDFLAGS = -no-undefined \ - -module \ - -avoid-version \ - -rpath $(gtkmoduledir) +libatk_bridge_la_LDFLAGS = -no-undefined \ + -module \ + -avoid-version \ + -rpath $(gtkmoduledir) -libspiatk_la_LIBADD = $(DBUS_GLIB_LIBS) \ - $(ATK_LIBS) \ - $(DBIND_LIBS) \ - $(DROUTE_LIBS) \ - $(top_builddir)/common/libspicommon.la +libatk_bridge_la_LIBADD = $(DBUS_GLIB_LIBS) \ + $(ATK_LIBS) \ + $(DBIND_LIBS) \ + $(DROUTE_LIBS) \ + $(top_builddir)/common/libspicommon.la -libspiatk_la_SOURCES = \ +libatk_bridge_la_SOURCES = \ accessible-adaptor.c \ accessible-marshaller.c \ accessible-marshaller.h \ @@ -45,3 +45,13 @@ libspiatk_la_SOURCES = \ tree-adaptor.c \ tree-adaptor.h \ value-adaptor.c + +gtkpathdir = $(gtkmoduledir)/.. +gnomeautostartdir = $(datadir)/gnome/autostart +gnomeautostart_DATA = atk-bridge.desktop +EXTRA_DIST = atk-bridge.desktop.in +CLEANFILES = $(gnome_autostart_DATA) + +%.desktop: %.desktop.in Makefile.am + sed -e "s,\@gtkpathdir\@,$(gtkpathdir)," \ + < $< > $@ diff --git a/atk-adaptor/atk-bridge.desktop.in b/atk-adaptor/atk-bridge.desktop.in new file mode 100644 index 0000000..016a2d3 --- /dev/null +++ b/atk-adaptor/atk-bridge.desktop.in @@ -0,0 +1,8 @@ +[Desktop Entry] +Type=Application +Name=GNOME D-Bus atk-bridge locator +Comment=Sets GTK_PATH for gnome-session to pick up D-Bus atk-bridge module +Exec=dbus-send --session --dest="org.gnome.SessionManager" /org/gnome/SessionManager org.gnome.SessionManager.Setenv string:"GTK_PATH" string:"@gtkpathdir@" +OnlyShowIn=GNOME; +AutostartCondition=GNOME /desktop/gnome/interface/atspi-dbus +X-GNOME-Autostart-Phase=Initialization diff --git a/configure.ac b/configure.ac index 7d588ce..860db2e 100644 --- a/configure.ac +++ b/configure.ac @@ -88,12 +88,24 @@ fi LIBTOOL_EXPORT_OPTIONS='-export-symbols-regex "^[[^cspi]].*"' AC_SUBST(LIBTOOL_EXPORT_OPTIONS) +# Extra libraries for sockets added by Willie Walker +# based upon how SunStudio libraries work. +# +if test "$GCC" = yes; then + EXTRA_SOCKET_LIBS="" +else + EXTRA_SOCKET_LIBS="-lsocket -lnsl" +fi +AC_SUBST(EXTRA_SOCKET_LIBS) + AC_CONFIG_FILES([Makefile pkgconfig/cspi-1.0.pc pkgconfig/cspi-1.0-uninstalled.pc common/Makefile atk-adaptor/Makefile cspi/Makefile + tests/Makefile + tests/cspi/Makefile ]) AC_OUTPUT diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 0000000..0f4206f --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = cspi diff --git a/tests/cspi/Makefile.am b/tests/cspi/Makefile.am new file mode 100644 index 0000000..f2e70a6 --- /dev/null +++ b/tests/cspi/Makefile.am @@ -0,0 +1,19 @@ +noinst_PROGRAMS = key-listener-test keysynth-test simple-at test-simple + +key_listener_test_SOURCES = key-listener-test.c +keysynth_test_SOURCES = keysynth-test.c +simple_at_SOURCES = simple-at.c +test_simple_SOURCES = test-simple.c + +INCLUDES = -I$(top_srcdir) \ + -I$(top_builddir) \ + $(DBUS_CFLAGS) \ + $(GLIB_CFLAGS) \ + $(GTK_CFLAGS) \ + $(ATK_CFLAGS) \ + $(DBIND_CFLAGS) \ + $(DEBUG_CFLAGS) + +LDADD = $(top_builddir)/common/libspicommon.la \ + $(top_builddir)/cspi/libcspi.la \ + $(TESTS_LIBS) $(X_LIBS) $(XINPUT_LIBS) $(ATK_LIBS) $(GTK_LIBS) $(DBIND_LIBS) @EXTRA_SOCKET_LIBS@ diff --git a/tests/cspi/key-listener-test.c b/tests/cspi/key-listener-test.c new file mode 100644 index 0000000..b212a21 --- /dev/null +++ b/tests/cspi/key-listener-test.c @@ -0,0 +1,201 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "../../cspi/spi.h" + +static SPIBoolean report_command_key_event (const AccessibleKeystroke *stroke, void *user_data); +static SPIBoolean report_ordinary_key_event (const AccessibleKeystroke *stroke, void *user_data); +static SPIBoolean report_synchronous_key_event (const AccessibleKeystroke *stroke, void *user_data); +static SPIBoolean report_tab_key_event (const AccessibleKeystroke *stroke, void *user_data); +static SPIBoolean report_all_key_event (const AccessibleKeystroke *stroke, void *user_data); + +static AccessibleKeystrokeListener *command_key_listener; +static AccessibleKeystrokeListener *ordinary_key_listener; +static AccessibleKeystrokeListener *synchronous_key_listener; +static AccessibleKeystrokeListener *tab_key_listener; +static AccessibleKeystrokeListener *all_key_listener; +static AccessibleKeySet *command_keyset; +static AccessibleKeySet *async_keyset; +static AccessibleKeySet *sync_keyset; +static AccessibleKeySet *tab_keyset; + +int +main (int argc, char **argv) +{ + const char *tab_strings[1] = {"Tab"}; + short keycodes[] = {65, 64, 23}; + SPIBoolean retval = FALSE; + + SPI_init (); + + /* prepare the keyboard snoopers */ + command_key_listener = SPI_createAccessibleKeystrokeListener (report_command_key_event, NULL); + ordinary_key_listener = SPI_createAccessibleKeystrokeListener (report_ordinary_key_event, NULL); + synchronous_key_listener = SPI_createAccessibleKeystrokeListener (report_synchronous_key_event, NULL); + tab_key_listener = SPI_createAccessibleKeystrokeListener (report_tab_key_event, NULL); + all_key_listener = SPI_createAccessibleKeystrokeListener (report_all_key_event, NULL); + + command_keyset = SPI_createAccessibleKeySet (1, "q", NULL, NULL); + async_keyset = SPI_createAccessibleKeySet (3, NULL, keycodes, NULL); + sync_keyset = SPI_createAccessibleKeySet (3, "def", NULL, NULL); + tab_keyset = SPI_createAccessibleKeySet (1, NULL, NULL, tab_strings); + retval = SPI_registerAccessibleKeystrokeListener(command_key_listener, + command_keyset, + SPI_KEYMASK_ALT | SPI_KEYMASK_CONTROL, + (unsigned long) ( SPI_KEY_PRESSED ), + SPI_KEYLISTENER_ALL_WINDOWS); + fprintf (stderr, "Command key registry: result %s\n", retval ? "succeeded" : + "failed"); + retval = SPI_registerAccessibleKeystrokeListener(ordinary_key_listener, + async_keyset, + SPI_KEYMASK_UNMODIFIED, + (unsigned long) ( SPI_KEY_PRESSED | SPI_KEY_RELEASED ), + SPI_KEYLISTENER_NOSYNC); + + retval = SPI_registerAccessibleKeystrokeListener(synchronous_key_listener, + sync_keyset, + SPI_KEYMASK_UNMODIFIED, + (unsigned long) ( SPI_KEY_PRESSED | SPI_KEY_RELEASED ), + SPI_KEYLISTENER_CANCONSUME); + + retval = SPI_registerAccessibleKeystrokeListener(tab_key_listener, + tab_keyset, + SPI_KEYMASK_ALT, + (unsigned long) ( SPI_KEY_PRESSED | SPI_KEY_RELEASED ), + SPI_KEYLISTENER_ALL_WINDOWS); + fprintf (stderr, "tab listener registry: %s\n", retval ? "succeeded" : "failed"); + + retval = SPI_registerAccessibleKeystrokeListener(all_key_listener, + SPI_KEYSET_ALL_KEYS, + SPI_KEYMASK_CONTROL | SPI_KEYMASK_SHIFT, + (unsigned long) ( SPI_KEY_PRESSED | SPI_KEY_RELEASED ), + SPI_KEYLISTENER_ALL_WINDOWS); + + fprintf (stderr, "all key registry: %s\n", retval ? "succeeded" : "failed" ); + + SPI_registerAccessibleKeystrokeListener(all_key_listener, + SPI_KEYSET_ALL_KEYS, + SPI_KEYMASK_SHIFT, + (unsigned long) ( SPI_KEY_PRESSED ), + SPI_KEYLISTENER_NOSYNC | SPI_KEYLISTENER_CANCONSUME); + + SPI_event_main (); + + putenv ("AT_BRIDGE_SHUTDOWN=1"); + + return SPI_exit (); +} + +static void +simple_at_exit (void) +{ + SPI_deregisterAccessibleKeystrokeListener (command_key_listener, SPI_KEYMASK_ALT | SPI_KEYMASK_CONTROL); + AccessibleKeystrokeListener_unref (command_key_listener); + SPI_freeAccessibleKeySet (command_keyset); + +/* + SPI_deregisterAccessibleKeystrokeListener (ordinary_key_listener, SPI_KEYMASK_ALT | SPI_KEYMASK_CONTROL); */ + AccessibleKeystrokeListener_unref (ordinary_key_listener); + SPI_freeAccessibleKeySet (async_keyset); + +/* SPI_deregisterAccessibleKeystrokeListener (synchronous_key_listener, SPI_KEYMASK_ALT | SPI_KEYMASK_CONTROL); */ + AccessibleKeystrokeListener_unref (synchronous_key_listener); + SPI_freeAccessibleKeySet (sync_keyset); + + SPI_deregisterAccessibleKeystrokeListener (tab_key_listener, SPI_KEYMASK_ALT | SPI_KEYMASK_CONTROL); + AccessibleKeystrokeListener_unref (tab_key_listener); + SPI_freeAccessibleKeySet (tab_keyset); + + SPI_event_quit (); +} + +static SPIBoolean +is_command_key (const AccessibleKeystroke *key) +{ + switch (key->keyID) + { + case 'Q': + case 'q': + simple_at_exit(); + return TRUE; /* not reached */ + default: + return FALSE; + } +} + +static void +print_key_event (const AccessibleKeystroke *key, char *prefix) +{ + fprintf (stderr, "%s KeyEvent %s%c (keycode %d); string=%s; time=%lx\n", + prefix, + (key->modifiers & SPI_KEYMASK_ALT)?"Alt-":"", + ((key->modifiers & SPI_KEYMASK_SHIFT)^(key->modifiers & SPI_KEYMASK_SHIFTLOCK))? + (char) toupper((int) key->keyID) : (char) tolower((int) key->keyID), + (int) key->keycode, + key->keystring, + (long int) key->timestamp); +} + +static SPIBoolean +report_command_key_event (const AccessibleKeystroke *key, void *user_data) +{ + print_key_event (key, "command"); + return is_command_key (key); +} + +static SPIBoolean +report_ordinary_key_event (const AccessibleKeystroke *key, void *user_data) +{ + print_key_event (key, "ordinary"); + return FALSE; +} + +static SPIBoolean +report_synchronous_key_event (const AccessibleKeystroke *key, void *user_data) +{ + /* consume 'd' key, let others pass through */ + print_key_event (key, "synchronous (consumable) "); + return ( key->keyID == 'd' ) ? TRUE : FALSE; +} + +static SPIBoolean +report_tab_key_event (const AccessibleKeystroke *key, void *user_data) +{ + print_key_event (key, "[TAB]"); + return FALSE; +} + +static SPIBoolean +report_all_key_event (const AccessibleKeystroke *key, void *user_data) +{ + fprintf(stderr, "(%ld)", key->keyID); + return FALSE; +} + diff --git a/tests/cspi/keysynth-test.c b/tests/cspi/keysynth-test.c new file mode 100644 index 0000000..73aa240 --- /dev/null +++ b/tests/cspi/keysynth-test.c @@ -0,0 +1,65 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include "../../cspi/spi-private.h" /* A hack for now */ +#include +#include +#include +#include +#include "common/spi-dbus.h" + +typedef struct { + long int val; + char *string; + AccessibleKeySynthType type; +} TextTest; + +static TextTest text[] = { + {65, NULL, SPI_KEY_PRESSRELEASE}, + {64, NULL, SPI_KEY_SYM}, + {0, "--hello!", SPI_KEY_STRING}, + {0, "StudlyCaps!", SPI_KEY_STRING} +}; + +static void +test_key_synthesis (void) +{ + int i; + for (i = 0; i < G_N_ELEMENTS (text); ++i) { + SPI_generateKeyboardEvent (text[i].val, text[i].string, text[i].type); + } +} + +int +main (int argc, char **argv) +{ + gtk_init (&argc, &argv); + SPI_init (); + + test_key_synthesis (); + + return SPI_exit (); +} + diff --git a/tests/cspi/simple-at.c b/tests/cspi/simple-at.c new file mode 100644 index 0000000..23cb0ec --- /dev/null +++ b/tests/cspi/simple-at.c @@ -0,0 +1,615 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#undef MAGNIFIER_ENABLED +#include "../../cspi/spi-private.h" /* A hack for now */ + +#define PRINT_TREE + +static void report_focus_event (const AccessibleEvent *event, void *user_data); +static void report_generic_event (const AccessibleEvent *event, void *user_data); +static void report_window_event (const AccessibleEvent *event, void *user_data); +static void report_text_event (const AccessibleEvent *event, void *user_data); +static void report_button_press (const AccessibleEvent *event, void *user_data); +static void check_property_change (const AccessibleEvent *event, void *user_data); +static SPIBoolean report_command_key_event (const AccessibleKeystroke *stroke, void *user_data); +static SPIBoolean report_ordinary_key_event (const AccessibleKeystroke *stroke, void *user_data); +static void get_environment_vars (void); + +static int _festival_init (void); +static void _festival_say (const char *text, const char *voice, SPIBoolean shutup); +static void _festival_write (const char *buff, int fd); + +#ifdef PRINT_TREE +static void print_accessible_tree (Accessible *accessible, char *prefix); +#endif + +#ifdef MAGNIFIER_ENABLED +static SPIBoolean use_magnifier = FALSE; +#endif + +static SPIBoolean use_festival = FALSE; +static SPIBoolean festival_chatty = FALSE; +static SPIBoolean name_changed = FALSE; + +static AccessibleEventListener *focus_listener; +static AccessibleEventListener *property_listener; +static AccessibleEventListener *generic_listener; +static AccessibleEventListener *window_listener; +static AccessibleEventListener *button_listener; +static AccessibleEventListener *text_listener; +static AccessibleKeystrokeListener *command_key_listener; +static AccessibleKeystrokeListener *ordinary_key_listener; +static AccessibleKeySet *command_keyset; + +int +main (int argc, char **argv) +{ + int i, j; + int n_desktops; + int n_apps; + char *s; + Accessible *desktop; + Accessible *application; + const char *modules; + + if ((argc > 1) && (!strncmp (argv[1], "-h", 2))) + { + printf ("Usage: simple-at\n"); + printf ("\tEnvironment variables used:\n\t\tFESTIVAL\n\t\tMAGNIFIER\n\t\tFESTIVAL_CHATTY\n"); + exit (0); + } + + modules = g_getenv ("GTK_MODULES"); + if (!modules || modules [0] == '\0') + { + putenv ("GTK_MODULES="); + } + modules = NULL; + + SPI_init (); + + focus_listener = SPI_createAccessibleEventListener (report_focus_event, NULL); + property_listener = SPI_createAccessibleEventListener (check_property_change, NULL); + generic_listener = SPI_createAccessibleEventListener (report_generic_event, NULL); + window_listener = SPI_createAccessibleEventListener (report_window_event, NULL); + text_listener = SPI_createAccessibleEventListener (report_text_event, NULL); + button_listener = SPI_createAccessibleEventListener (report_button_press, NULL); + SPI_registerGlobalEventListener (focus_listener, "focus:"); + SPI_registerGlobalEventListener (property_listener, "object:property-change"); +/* :accessible-selection"); */ + SPI_registerGlobalEventListener (property_listener, "object:property-change:accessible-name"); + SPI_registerGlobalEventListener (generic_listener, "object:selection-changed"); + SPI_registerGlobalEventListener (generic_listener, "object:children-changed"); + SPI_registerGlobalEventListener (generic_listener, "object:visible-data-changed"); + SPI_registerGlobalEventListener (generic_listener, "object:text-selection-changed"); + SPI_registerGlobalEventListener (text_listener, "object:text-caret-moved"); + SPI_registerGlobalEventListener (text_listener, "object:text-changed"); + SPI_registerGlobalEventListener (button_listener, "Gtk:GtkWidget:button-press-event"); + SPI_registerGlobalEventListener (window_listener, "window:minimize"); + SPI_registerGlobalEventListener (window_listener, "window:activate"); + n_desktops = SPI_getDesktopCount (); + + for (i=0; i 0) + { + AccessibleText_getCharacterExtents (text, 0, &x0, &y0, &w0, &h0, + SPI_COORD_TYPE_SCREEN); + AccessibleText_getCharacterExtents (text, nchars-1, &xN, &yN, &wN, &hN, + SPI_COORD_TYPE_SCREEN); + x = MIN (x0, xN); + width = MAX (x0 + w0, xN + wN) - x; + fprintf (stderr, "Text bounding box: (%ld, %ld) ; (%ld, %ld)\n", + x, y, x+width, y+height); + } + } +#ifdef MAGNIFIER_ENABLED + if (use_magnifier) { + magnifier_set_roi ((short) 0, x, y, width, height); + } +#endif + } + + + if (Accessible_isValue (obj)) + { + AccessibleValue *value = Accessible_getValue (obj); + fprintf (stderr, "Current value = %f, min = %f; max = %f\n", + AccessibleValue_getCurrentValue (value), + AccessibleValue_getMinimumValue (value), + AccessibleValue_getMaximumValue (value)); + } + /* if this is a text object, speak the first sentence. */ + + if (Accessible_isText(obj)) + + { + AccessibleText *text_interface; + long start_offset, end_offset; + char *first_sentence = "empty"; + text_interface = Accessible_getText (obj); + first_sentence = AccessibleText_getTextAtOffset ( + text_interface, (long) 0, SPI_TEXT_BOUNDARY_SENTENCE_START, &start_offset, &end_offset); + if (first_sentence && use_festival) + { + _festival_say(first_sentence, "voice_don_diphone", FALSE); + SPI_freeString (first_sentence); + } + len = AccessibleText_getCharacterCount (text_interface); + s = AccessibleText_getText (text_interface, 0, len); + fprintf (stderr, "done reporting on focussed object, text=%s\n", s); + } +} + +void +report_focus_event (const AccessibleEvent *event, void *user_data) +{ + char *s; + + g_return_if_fail (event->source != NULL); + s = Accessible_getName (event->source); + if (s) + { + fprintf (stderr, "%s event from %s\n", event->type, s); + SPI_freeString (s); + report_focussed_accessible (event->source, TRUE); + } + Accessible_getParent (event->source); + name_changed = FALSE; +} + +void +report_generic_event (const AccessibleEvent *event, void *user_data) +{ + fprintf (stderr, "%s event received\n", event->type); +} + +void +report_window_event (const AccessibleEvent *event, void *user_data) +{ + fprintf (stderr, "%s event received\n", event->type); + if (!strcmp (event->type, "window:activate")) + { + print_accessible_tree (event->source, "window"); + } +} + +void +report_text_event (const AccessibleEvent *event, void *user_data) +{ + AccessibleText *text = Accessible_getText (event->source); + fprintf (stderr, "%s event received\n", event->type); +#ifdef MAGNIFIER_ENABLED + if (use_magnifier && strcmp (event->type, "object:text-changed")) + { + long offset = AccessibleText_getCaretOffset (text); + long x, y, w, h; + fprintf (stderr, "offset %d\n", (int) offset); + AccessibleText_getCharacterExtents (text, offset, &x, &y, &w, &h, + SPI_COORD_TYPE_SCREEN); + fprintf (stderr, "new roi %d %d %d %d\n", (int) x, (int) y, (int) w, (int) h); + magnifier_set_roi ((short) 0, x, y, w, h); + } +#endif + if (!strcmp (event->type, "object:text-changed")) + { + long start, end; + char *new_text = AccessibleText_getTextAtOffset (text, (long) event->detail1, SPI_TEXT_BOUNDARY_WORD_START, &start, &end); + _festival_say (new_text, "voice_kal_diphone", FALSE); + fprintf (stderr, "text changed: %s", new_text ? new_text : ""); + SPI_freeString (new_text); + } + else + { + long start, end; + char *word_text = AccessibleText_getTextAtOffset (text, (long) event->detail1, SPI_TEXT_BOUNDARY_WORD_START, &start, &end); + char *sentence_text = AccessibleText_getTextAtOffset (text, (long) event->detail1, SPI_TEXT_BOUNDARY_SENTENCE_START, &start, &end); + fprintf (stderr, "text changed: word %s; sentence %s at %ld", + (word_text ? word_text : ""), + (sentence_text ? sentence_text : ""), + event->detail1); + if (word_text) SPI_freeString (word_text); + if (sentence_text) SPI_freeString (sentence_text); + } +} + +void +report_button_press (const AccessibleEvent *event, void *user_data) +{ + char *s; + + g_return_if_fail (event->source != NULL); + + s = Accessible_getName (event->source); + + fprintf (stderr, "%s event from %s\n", event->type, s); + SPI_freeString (s); + s = Accessible_getDescription (event->source); + fprintf (stderr, "Object description %s\n", s); + SPI_freeString (s); +} + +void +check_property_change (const AccessibleEvent *event, void *user_data) +{ + AccessibleSelection *selection = Accessible_getSelection (event->source); + int n_selections; + int i; + char *s; + fprintf (stderr, "property change event!\n"); + if (selection) + { + n_selections = (int) AccessibleSelection_getNSelectedChildren (selection); + s = Accessible_getName (event->source); + fprintf (stderr, "(Property) %s event from %s, %d selected children\n", + event->type, s, n_selections); + SPI_freeString (s); + /* for now, speak entire selection set */ + for (i=0; itype, "object:property-change:accessible-name")) + { + name_changed = TRUE; + report_focussed_accessible (event->source, TRUE); + } + else + { + fprintf (stderr, "Property change %s received\n", event->type); + } +} + +static void +simple_at_exit (void) +{ + SPI_deregisterGlobalEventListenerAll (focus_listener); + AccessibleEventListener_unref (focus_listener); + + SPI_deregisterGlobalEventListenerAll (property_listener); + AccessibleEventListener_unref (property_listener); + + SPI_deregisterGlobalEventListenerAll (generic_listener); + AccessibleEventListener_unref (generic_listener); + + SPI_deregisterGlobalEventListenerAll (text_listener); + AccessibleEventListener_unref (text_listener); + + SPI_deregisterGlobalEventListenerAll (button_listener); + AccessibleEventListener_unref (button_listener); + + SPI_deregisterAccessibleKeystrokeListener (command_key_listener, SPI_KEYMASK_ALT | SPI_KEYMASK_CONTROL); + AccessibleKeystrokeListener_unref (command_key_listener); + SPI_freeAccessibleKeySet (command_keyset); + + SPI_deregisterAccessibleKeystrokeListener (ordinary_key_listener, SPI_KEYMASK_SHIFTLOCK); + AccessibleKeystrokeListener_unref (ordinary_key_listener); + + SPI_event_quit (); +} + +static SPIBoolean +is_command_key (const AccessibleKeystroke *key) +{ + switch (key->keyID) + { + case 'Q': + case 'q': + simple_at_exit(); + return TRUE; /* not reached */ +#ifdef MAGNIFIER_ENABLED + case 'M': + case 'm': + use_magnifier = ! use_magnifier; + fprintf (stderr, "%ssing magnifier\n", use_magnifier ? "U" : "Not u"); + return TRUE; +#endif + case 'F': + case 'f': + use_festival = ! use_festival; + fprintf (stderr, "%speech output\n", use_festival ? "S" : "No s"); + return TRUE; + default: + return FALSE; + } +} + +static SPIBoolean +report_command_key_event (const AccessibleKeystroke *key, void *user_data) +{ + fprintf (stderr, "Command KeyEvent %s%c (keycode %d); string=%s; time=%lx\n", + (key->modifiers & SPI_KEYMASK_ALT)?"Alt-":"", + ((key->modifiers & SPI_KEYMASK_SHIFT)^(key->modifiers & SPI_KEYMASK_SHIFTLOCK))? + (char) toupper((int) key->keyID) : (char) tolower((int) key->keyID), + (int) key->keycode, + key->keystring, + (long int) key->timestamp); + return is_command_key (key); +} + + +static SPIBoolean +report_ordinary_key_event (const AccessibleKeystroke *key, void *user_data) +{ + fprintf (stderr, "Received key event:\tsym %ld\n\tmods %x\n\tcode %d\n\tstring=\'%s\'\n\ttime %lx\n", + (long) key->keyID, + (unsigned int) key->modifiers, + (int) key->keycode, + key->keystring, + (long int) key->timestamp); + return FALSE; +} + +static int +_festival_init (void) +{ + int fd; + struct sockaddr_in name; + int tries = 2; + + name.sin_family = AF_INET; + name.sin_port = htons (1314); + name.sin_addr.s_addr = htonl(INADDR_ANY); + fd = socket (PF_INET, SOCK_STREAM, 0); + + while (connect(fd, (struct sockaddr *) &name, sizeof (name)) < 0) { + if (!tries--) { + perror ("connect"); + return -1; + } + } + + _festival_write ("(audio_mode'async)\n", fd); + _festival_write ("(Parameter.set 'Duration_Model 'Tree_ZScore)\n", fd); + _festival_write ("(Parameter.set 'Duration_Stretch 0.75)\n", fd); + return fd; +} + +static void +_festival_say (const char *text, const char *voice, SPIBoolean shutup) +{ + static int fd = 0; + gchar *quoted; + gchar *p; + gchar prefix[50]; + static gchar voice_spec[32]; + + if (!fd) + { + fd = _festival_init (); + } + + fprintf (stderr, "saying text: %s\n", text); + + quoted = g_malloc(64+strlen(text)*2); + + sprintf (prefix, "(SayText \""); + + strncpy(quoted, prefix, 10); + p = quoted+strlen(prefix); + while (*text) { + if ( *text == '\\' || *text == '"' ) + *p = '\\'; + *p++ = *text++; + } + *p++ = '"'; + *p++ = ')'; + *p++ = '\n'; + *p = 0; + + if (shutup) _festival_write ("(audio_mode'shutup)\n", fd); + if (voice && (strncmp (voice, (char *) (voice_spec+1), strlen(voice)))) + { + snprintf (voice_spec, 32, "(%s)\n", voice); + _festival_write (voice_spec, fd); + _festival_write ("(Parameter.set 'Duration_Model 'Tree_ZScore)\n", fd); + _festival_write ("(Parameter.set 'Duration_Stretch 0.75)\n", fd); + } + + _festival_write (quoted, fd); + + g_free(quoted); +} + +static void +_festival_write (const gchar *command_string, int fd) +{ + fprintf(stderr, command_string); + if (fd < 0) { + perror("socket"); + return; + } + write(fd, command_string, strlen(command_string)); +} + diff --git a/tests/cspi/test-simple.c b/tests/cspi/test-simple.c new file mode 100644 index 0000000..62bcb31 --- /dev/null +++ b/tests/cspi/test-simple.c @@ -0,0 +1,816 @@ +/* + * test-simple.c: A set of simple regression tests + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001 Ximian, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * ******** Do not copy this code as an example ********* + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "dbus/dbus.h" + +/* Known bugs */ +#define WHOLE_STRING -1 + +static void validate_accessible (Accessible *accessible, + gboolean has_parent, + gboolean recurse_down); + +#define WINDOW_MAGIC 0x123456a +#define TEST_STRING_A "A test string" +#define TEST_STRING_A_OBJECT "A_test_string_object" +#define TEST_STRING_B "Another test string" + +static int print_tree_depth = 0; +static gboolean print_tree = FALSE; +static gboolean do_poke = FALSE; +static gboolean key_press_received = FALSE; +static gboolean key_release_received = FALSE; + +typedef struct { + gulong magic; + GtkWidget *window; +} TestWindow; + +static gboolean +focus_me (GtkWidget *widget) +{ + AtkObject *aobject = atk_implementor_ref_accessible ( + ATK_IMPLEMENTOR (widget)); + + /* Force a focus event - even if the WM focused + * us before our at-bridge's idle handler registered + * our interest */ + if (!GTK_WIDGET_HAS_FOCUS (widget)) + gtk_widget_grab_focus (widget); +/* else: FIXME - gtk_widget_grab_focus should send a notify */ + atk_focus_tracker_notify (aobject); + + g_object_unref (G_OBJECT (aobject)); + + return FALSE; +} + +static void +test_window_add_and_show (GtkContainer *container, GtkWidget *widget) +{ + gtk_container_add (container, widget); + gtk_widget_show (widget); +} + +static GtkWidget * +create_tree (void) +{ + GtkWidget *widget; + GtkTreeIter iter; + GtkListStore *store; + GtkTreeViewColumn *column; + + store = gtk_list_store_new (1, G_TYPE_STRING); + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, 0, TEST_STRING_A, -1); + column = gtk_tree_view_column_new_with_attributes ("String", + gtk_cell_renderer_text_new (), "text", 0, NULL); + widget = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store)); + g_object_unref (G_OBJECT (store)); + gtk_tree_view_append_column (GTK_TREE_VIEW (widget), column); + + return widget; +} + +static TestWindow * +create_test_window (void) +{ + TestWindow *win = g_new0 (TestWindow, 1); + GtkWidget *widget, *vbox; + AtkObject *obj; + + win->magic = WINDOW_MAGIC; + win->window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + + gtk_widget_show (win->window); + + vbox = gtk_vbox_new (0, 0); + gtk_container_add (GTK_CONTAINER (win->window), vbox); + gtk_widget_show (vbox); + + widget = gtk_entry_new (); + gtk_entry_set_text (GTK_ENTRY (widget), TEST_STRING_A); + obj = gtk_widget_get_accessible (widget); + atk_object_set_name (obj, TEST_STRING_A_OBJECT); + + test_window_add_and_show (GTK_CONTAINER (vbox), widget); + + widget = gtk_button_new_with_label ("_Foobar"); + test_window_add_and_show (GTK_CONTAINER (vbox), widget); + + widget = gtk_hseparator_new (); + test_window_add_and_show (GTK_CONTAINER (vbox), widget); + + widget = gtk_image_new_from_stock (GTK_STOCK_DIALOG_QUESTION, + GTK_ICON_SIZE_LARGE_TOOLBAR); + test_window_add_and_show (GTK_CONTAINER (vbox), widget); + + widget = g_object_new (GTK_TYPE_HSCALE, NULL); + gtk_range_set_range (GTK_RANGE (widget), 0.0, 100.0); + test_window_add_and_show (GTK_CONTAINER (vbox), widget); + + widget = create_tree (); + test_window_add_and_show (GTK_CONTAINER (vbox), widget); + + g_idle_add ((GSourceFunc) focus_me, win->window); + + return win; +} + +static void +test_window_destroy (TestWindow *win) +{ + gtk_widget_destroy (win->window); + g_free (win); +} + +static void +test_roles (void) +{ + int i; + + fprintf (stderr, "Testing roles...\n"); + for (i = -1; i < 1000; i++) + g_assert (AccessibleRole_getName (i) != NULL); + + g_assert (!strcmp (AccessibleRole_getName (SPI_ROLE_FILE_CHOOSER), "file-chooser")); + g_assert (!strcmp (AccessibleRole_getName (SPI_ROLE_RADIO_BUTTON), "radio-button")); + g_assert (!strcmp (AccessibleRole_getName (SPI_ROLE_TABLE), "table")); + g_assert (!strcmp (AccessibleRole_getName (SPI_ROLE_WINDOW), "window")); +} + +static void +test_action (AccessibleAction *action) +{ + gint n_actions, i; + gchar *s, *sd; + g_assert ((n_actions = AccessibleAction_getNActions (action)) >= 0); + + fprintf (stderr, "Testing actions..."); + for (i = 0; i < n_actions; ++i) + { + s = AccessibleAction_getName (action, i); + g_assert (s); + sd = AccessibleAction_getDescription (action, i); + g_assert (sd); + fprintf (stderr, "%d: %s (%s); ", i, s, sd); + SPI_freeString (s); + SPI_freeString (sd); + g_assert (AccessibleAction_doAction (action, i)); + } + fprintf (stderr, "\n"); +} + +static void +test_desktop (void) +{ + Accessible *desktop; + Accessible *application; + Accessible **list; + + fprintf (stderr, "Testing desktop...\n"); + + g_assert (SPI_getDesktop (-1) == NULL); + desktop = SPI_getDesktop (0); + g_assert (desktop != NULL); + + g_assert ((SPI_getDesktopList (&list)) > 0); + g_assert (list[0] == desktop); + SPI_freeDesktopList (list); + + validate_accessible (desktop, FALSE, FALSE); + + application = Accessible_getChildAtIndex (desktop, 0); + g_assert (application != NULL); + AccessibleApplication_unref (application); + + Accessible_unref (desktop); +} + +static void +test_application (Accessible *application) +{ + char *str; + + fprintf (stderr, "Testing application ...\n"); + g_assert (Accessible_isApplication (application)); + g_assert (Accessible_getApplication (application) == + application); + AccessibleApplication_unref (application); + + str = AccessibleApplication_getToolkitName (application); + g_assert (str != NULL); + g_assert (!strcmp (str, "GAIL")); + SPI_freeString (str); + + str = AccessibleApplication_getLocale (application, LC_MESSAGES); + g_assert (!strcmp (str, setlocale (LC_MESSAGES, NULL))); + SPI_freeString (str); + + str = AccessibleApplication_getVersion (application); + g_assert (str != NULL); + SPI_freeString (str); + + AccessibleApplication_getID (application); +} + +static void +test_editable_text (AccessibleEditableText *etext) +{ + char *str; + AccessibleText *text; + + fprintf (stderr, "Testing editable text ...\n"); + + g_assert (Accessible_isText (etext)); + text = Accessible_getText (etext); + + AccessibleEditableText_setTextContents ( + etext, TEST_STRING_B); + + str = AccessibleText_getText (text, 0, WHOLE_STRING); + g_assert (!strcmp (str, TEST_STRING_B)); + + SPI_freeString (str); + + /* FIXME: lots more editing here */ + + AccessibleEditableText_setTextContents ( + etext, TEST_STRING_A); + + AccessibleText_unref (text); +} + +static void +test_table (AccessibleTable *table) +{ + Accessible *header; + gint index; + gint rows, columns; + + fprintf (stderr, "Testing table ...\n"); + + rows = AccessibleTable_getNRows (table); + g_assert (rows > 0); + + columns = AccessibleTable_getNColumns (table); + g_assert (columns > 0); + + index = AccessibleTable_getIndexAt (table, rows - 1, columns - 1); + + g_assert (AccessibleTable_getRowAtIndex (table, index) == rows - 1); + + g_assert (AccessibleTable_getColumnAtIndex (table, index) == columns - 1); + + g_assert ((header = AccessibleTable_getColumnHeader (table, 0))); + Accessible_unref (header); + + AccessibleTable_isSelected (table, 0, 0); + + /* FIXME: lots more tests */ +} + +static void +test_text (AccessibleText *text) +{ + char *str; + + fprintf (stderr, "Testing text ...\n"); + + g_assert (AccessibleText_getCharacterCount (text) == + strlen (TEST_STRING_A)); + + str = AccessibleText_getText (text, 0, WHOLE_STRING); + g_assert (!strcmp (str, TEST_STRING_A)); + SPI_freeString (str); + + str = AccessibleText_getText (text, 0, 5); + g_assert (!strncmp (str, TEST_STRING_A, 5)); + SPI_freeString (str); + + AccessibleText_setCaretOffset (text, 7); + g_assert (AccessibleText_getCaretOffset (text) == 7); + + /* FIXME: lots more tests - selections etc. etc. */ +} + +static void +test_value (AccessibleValue *value) +{ + float original_value; + + fprintf (stderr, "Testing value ...\n"); + + original_value = AccessibleValue_getCurrentValue (value); + + g_assert (AccessibleValue_getCurrentValue (value) <= + AccessibleValue_getMaximumValue (value)); + + g_assert (AccessibleValue_getCurrentValue (value) >= + AccessibleValue_getMinimumValue (value)); + + AccessibleValue_setCurrentValue (value, + AccessibleValue_getMinimumValue (value)); + + g_assert (AccessibleValue_getCurrentValue (value) == + AccessibleValue_getMinimumValue (value)); + + AccessibleValue_setCurrentValue (value, + AccessibleValue_getMaximumValue (value)); + + g_assert (AccessibleValue_getCurrentValue (value) == + AccessibleValue_getMaximumValue (value)); + + AccessibleValue_setCurrentValue (value, original_value); + + g_assert (AccessibleValue_getCurrentValue (value) == original_value); +} + +static void +test_component (AccessibleComponent *component) +{ + long x, y, width, height; + + fprintf (stderr, "Testing component...\n"); + + AccessibleComponent_getExtents ( + component, &x, &y, &width, &height, SPI_COORD_TYPE_SCREEN); + + AccessibleComponent_getPosition ( + component, &x, &y, SPI_COORD_TYPE_SCREEN); + + AccessibleComponent_getSize (component, &width, &height); + + if (width > 0 && height > 0) { +#ifdef FIXME + Accessible *accessible, *componentb; +#endif + + g_assert (AccessibleComponent_contains ( + component, x, y, SPI_COORD_TYPE_SCREEN)); + + g_assert (AccessibleComponent_contains ( + component, x + width - 1, y, SPI_COORD_TYPE_SCREEN)); + + g_assert (AccessibleComponent_contains ( + component, x + width - 1, y + height - 1, + SPI_COORD_TYPE_SCREEN)); + +#ifdef FIXME + accessible = AccessibleComponent_getAccessibleAtPoint ( + component, x, y, SPI_COORD_TYPE_SCREEN); + + g_assert (Accessible_isComponent (accessible)); + componentb = Accessible_getComponent (accessible); + g_assert (componentb == component); + + AccessibleComponent_unref (componentb); + Accessible_unref (accessible); +#endif + } + + AccessibleComponent_getLayer (component); + AccessibleComponent_getMDIZOrder (component); +/* AccessibleComponent_grabFocus (component); */ +} + +static void +test_image (AccessibleImage *image) +{ + char *desc; + long int x = -1, y = -1, width = -1, height = -1; + + desc = AccessibleImage_getImageDescription (image); + g_assert (desc != NULL); + SPI_freeString (desc); + + AccessibleImage_getImagePosition (image, &x, &y, + SPI_COORD_TYPE_SCREEN); + AccessibleImage_getImageSize (image, &width, &height); + AccessibleImage_getImageExtents (image, &x, &y, &width, &height, + SPI_COORD_TYPE_WINDOW); +} + +static void +validate_tree (Accessible *accessible, + gboolean has_parent, + gboolean recurse_down) +{ + Accessible *parent; + long len, i; + + parent = Accessible_getParent (accessible); + if (has_parent) { + long index; + Accessible *child_at_index; + + g_assert (parent != NULL); + + index = Accessible_getIndexInParent (accessible); + g_assert (index >= 0); + + child_at_index = Accessible_getChildAtIndex (parent, index); + + g_assert (child_at_index == accessible); + + Accessible_unref (child_at_index); + Accessible_unref (parent); + } + + len = Accessible_getChildCount (accessible); + print_tree_depth++; + for (i = 0; i < len; i++) { + Accessible *child; + + child = Accessible_getChildAtIndex (accessible, i); +#ifdef ROPEY + if (!child) + fprintf (stderr, "Unusual - ChildGone at %ld\n", i); + + g_assert (Accessible_getIndexInParent (child) == i); + g_assert (Accessible_getParent (child) == accessible); +#endif + + if (recurse_down && child) + validate_accessible (child, has_parent, recurse_down); + + Accessible_unref (child); + } + print_tree_depth--; +} + +static void +validate_accessible (Accessible *accessible, + gboolean has_parent, + gboolean recurse_down) +{ + Accessible *tmp; + char *name, *descr; + AccessibleRole role; + AccessibleRelation **relations; + char *role_name; + GString *item_str = g_string_new (""); + int i; + + name = Accessible_getName (accessible); + g_assert (name != NULL); + + descr = Accessible_getDescription (accessible); + g_assert (descr != NULL); + + role = Accessible_getRole (accessible); + g_assert (role != SPI_ROLE_INVALID); + role_name = Accessible_getRoleName (accessible); + g_assert (role_name != NULL); + + relations = Accessible_getRelationSet (accessible); + g_assert (relations != NULL); + + for (i = 0; relations [i]; i++) { + AccessibleRelationType type; + int targets; + + fprintf (stderr, "relation %d\n", i); + + type = AccessibleRelation_getRelationType (relations [i]); + g_assert (type != SPI_RELATION_NULL); + + targets = AccessibleRelation_getNTargets (relations [i]); + g_assert (targets != -1); + + AccessibleRelation_unref (relations [i]); + relations [i] = NULL; + } + free (relations); + + if (print_tree) { + int i; + + for (i = 0; i < print_tree_depth; i++) + fputc (' ', stderr); + fputs ("|-> [ ", stderr); + } + + if (Accessible_isAction (accessible)) { + tmp = Accessible_getAction (accessible); + g_assert (tmp != NULL); + if (print_tree) + fprintf (stderr, "At"); + else + test_action (tmp); + AccessibleAction_unref (tmp); + } + + if (Accessible_isApplication (accessible)) { + tmp = Accessible_getApplication (accessible); + if (print_tree) + fprintf (stderr, "Ap"); + else + test_application (tmp); + AccessibleApplication_unref (tmp); + } + + if (Accessible_isComponent (accessible)) { + tmp = Accessible_getComponent (accessible); + g_assert (tmp != NULL); + if (print_tree) + fprintf (stderr, "Co"); + else + test_component (tmp); + AccessibleComponent_unref (tmp); + } + + if (Accessible_isEditableText (accessible)) { + tmp = Accessible_getEditableText (accessible); + g_assert (tmp != NULL); + if (print_tree) + fprintf (stderr, "Et"); + else + test_editable_text (tmp); + AccessibleEditableText_unref (tmp); + } + + if (Accessible_isHypertext (accessible)) { + tmp = Accessible_getHypertext (accessible); + g_assert (tmp != NULL); + if (print_tree) + fprintf (stderr, "Ht"); + AccessibleHypertext_unref (tmp); + } + + if (Accessible_isImage (accessible)) { + tmp = Accessible_getImage (accessible); + g_assert (tmp != NULL); + if (print_tree) { + char *desc; + + fprintf (stderr, "Im"); + + desc = AccessibleImage_getImageDescription (tmp); + g_string_append_printf ( + item_str, " image descr: '%s'", desc); + SPI_freeString (desc); + } else + test_image (tmp); + + AccessibleImage_unref (tmp); + } + + if (Accessible_isSelection (accessible)) { + tmp = Accessible_getSelection (accessible); + g_assert (tmp != NULL); + if (print_tree) + fprintf (stderr, "Se"); + AccessibleSelection_unref (tmp); + } + + if (Accessible_isTable (accessible)) { + tmp = Accessible_getTable (accessible); + g_assert (tmp != NULL); + if (print_tree) + fprintf (stderr, "Ta"); + else + test_table (tmp); + AccessibleTable_unref (tmp); + } + + if (Accessible_isText (accessible)) { + tmp = Accessible_getText (accessible); + g_assert (tmp != NULL); + if (print_tree) + fprintf (stderr, "Te"); + else { + if (strcmp (name, TEST_STRING_A_OBJECT) == 0) + test_text (tmp); + } + AccessibleText_unref (tmp); + } + + if (Accessible_isValue (accessible)) { + tmp = Accessible_getValue (accessible); + g_assert (tmp != NULL); + if (print_tree) + fprintf (stderr, "Va"); + else + test_value (tmp); + AccessibleValue_unref (tmp); + } + + if (print_tree) + fprintf (stderr, " ] '%s' (%s) - %s: %s\n", + name, descr, role_name, item_str->str); + + SPI_freeString (name); + SPI_freeString (descr); + SPI_freeString (role_name); + g_string_free (item_str, TRUE); + + validate_tree (accessible, has_parent, recurse_down); +} + +static void +test_misc (void) +{ + fprintf (stderr, "Testing misc bits ...\n"); + + g_assert (!Accessible_isComponent (NULL)); + g_assert (Accessible_getComponent (NULL) == NULL); + SPI_freeString (NULL); +} + +static void +global_listener_cb (const AccessibleEvent *event, + void *user_data) +{ + TestWindow *win = user_data; + Accessible *desktop; + AccessibleApplication *application; + + g_assert (win->magic == WINDOW_MAGIC); + g_assert (!strcmp (event->type, "focus:")); + + fprintf (stderr, "Fielded focus event ...\n"); + + if (!do_poke) { + desktop = SPI_getDesktop (0); + application = Accessible_getChildAtIndex (desktop, 0); + g_assert (application != NULL); + Accessible_unref (desktop); + + test_application (application); + + AccessibleApplication_unref (application); + + print_tree = FALSE; + + validate_accessible (event->source, TRUE, TRUE); + + fprintf (stderr, "quitting mainloop.\n"); + gtk_main_quit (); + } + + print_tree = TRUE; + validate_accessible (event->source, TRUE, TRUE); +} + +static SPIBoolean +key_listener_cb (const AccessibleKeystroke *stroke, + void *user_data) +{ + AccessibleKeystroke *s = user_data; + + *s = *stroke; + if (stroke->keystring) s->keystring = g_strdup (stroke->keystring); + + if (s->type == SPI_KEY_PRESSED) + key_press_received = TRUE; + else if (s->type == SPI_KEY_RELEASED) + key_release_received = TRUE; + + return TRUE; +} + + +static void +test_keylisteners (void) +{ + int i; + AccessibleKeystroke stroke; + AccessibleKeystrokeListener *key_listener; + AccessibleKeySet *test_keyset; + + fprintf (stderr, "Testing keyboard listeners ...\n"); + + key_listener = SPI_createAccessibleKeystrokeListener ( + key_listener_cb, &stroke); + + test_keyset = SPI_createAccessibleKeySet (1, "=", NULL, NULL); + + g_assert (SPI_registerAccessibleKeystrokeListener ( + key_listener, + test_keyset, + 0, + SPI_KEY_PRESSED | SPI_KEY_RELEASED, + SPI_KEYLISTENER_CANCONSUME | SPI_KEYLISTENER_ALL_WINDOWS)); + + for (i = 0; i < 3; i++) { + memset (&stroke, 0, sizeof (AccessibleKeystroke)); + g_assert (SPI_generateKeyboardEvent ('=', NULL, SPI_KEY_SYM)); + while (!(key_press_received)) + g_main_context_iteration (NULL, TRUE); + fprintf (stderr, "p [%s]", stroke.keystring); + g_assert (!strcmp (stroke.keystring, "=")); + while (!(key_release_received)) + g_main_context_iteration (NULL, TRUE); + fprintf (stderr, "r [%s]", stroke.keystring); + key_press_received = FALSE; + key_release_received = FALSE; + } + g_assert (SPI_deregisterAccessibleKeystrokeListener (key_listener, 0)); + SPI_freeAccessibleKeySet (test_keyset); + + fprintf (stderr, "\n"); + + AccessibleKeystrokeListener_unref (key_listener); + + g_assert (SPI_generateMouseEvent (100, 100, "rel")); + g_assert (SPI_generateMouseEvent (-50, -50, "rel")); + g_assert (SPI_generateMouseEvent (-50, -50, "rel")); + g_assert (SPI_generateMouseEvent (-1, -1, "b1c")); +} + +int +main (int argc, char **argv) +{ + int leaked, i; + TestWindow *win; + const char *modules; + AccessibleEventListener *global_listener; + + modules = g_getenv ("GTK_MODULES"); + if (!modules || modules [0] == '\0') + putenv ("GTK_MODULES=gail:atk-bridge"); + modules = NULL; + + for (i = 1; i < argc; i++) { + if (!g_strcasecmp (argv [i], "--poke")) + do_poke = TRUE; + } + + gtk_init (&argc, &argv); + + g_assert (!SPI_init ()); + g_assert (SPI_init ()); + g_assert (SPI_getDesktopCount () == 1); + + test_roles (); + test_misc (); + test_desktop (); + test_keylisteners (); + + win = create_test_window (); + + global_listener = SPI_createAccessibleEventListener (global_listener_cb, win); + + g_assert (SPI_registerGlobalEventListener (global_listener, "focus:")); + + fprintf (stderr, "Waiting for focus event ...\n"); + gtk_main (); + + g_assert (SPI_deregisterGlobalEventListenerAll (global_listener)); + AccessibleEventListener_unref (global_listener); + + test_window_destroy (win); + + /* Wait for any pending events from the registry */ + g_usleep (500*1000); + for (i = 0; i < 100; i++) + dbus_connection_read_write_dispatch (SPI_bus(), 5); + + if ((leaked = SPI_exit ())) + g_error ("Leaked %d SPI handles", leaked); + + g_assert (!SPI_exit ()); + + fprintf (stderr, "All tests passed\n"); + + if (g_getenv ("_MEMPROF_SOCKET")) { + fprintf (stderr, "Waiting for memprof\n"); + gtk_main (); + } + + putenv ("AT_BRIDGE_SHUTDOWN=1"); + + return 0; +}