1571d4003ef11ad819cbc58752d9ca0f832c06d2
[platform/core/uifw/at-spi2-atk.git] / test / event-listener-test.c
1 /*
2  * AT-SPI - Assistive Technology Service Provider Interface
3  * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
4  *
5  * Copyright 2001, 2002, 2003 Sun Microsystems Inc.,
6  * Copyright 2001, 2002, 2003 Ximian, Inc.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include "../cspi/spi-private.h" /* A hack for now */
28
29 static void traverse_accessible_tree (Accessible *accessible);
30
31 static void report_event  (const AccessibleEvent *event, void *user_data);
32 static void report_caret_event  (const AccessibleEvent *event, void *user_data);
33 static void report_bounds_event  (const AccessibleEvent *event, void *user_data);
34 static void report_detail_event  (const AccessibleEvent *event, void *user_data);
35 static void report_detail1_event  (const AccessibleEvent *event, void *user_data);
36 static void report_text_event  (const AccessibleEvent *event, void *user_data);
37 static void report_text_selection_event  (const AccessibleEvent *event, void *user_data);
38 static void report_active_descendant_changed_event  (const AccessibleEvent *event, void *user_data);
39 static void report_children_changed_event (const AccessibleEvent *event, void *user_data);
40 static void report_name_changed_event (const AccessibleEvent *event, void *user_data);
41 static void report_description_changed_event (const AccessibleEvent *event, void *user_data);
42 static void report_parent_changed_event (const AccessibleEvent *event, void *user_data);
43 static void report_window_event  (const AccessibleEvent *event, void *user_data);
44 static void report_table_summary_event  (const AccessibleEvent *event, void *user_data);
45 static void report_table_header_event  (const AccessibleEvent *event, void *user_data);
46 static void report_table_caption_event  (const AccessibleEvent *event, void *user_data);
47 static void report_table_row_description_event  (const AccessibleEvent *event, void *user_data);
48 static void report_table_column_description_event  (const AccessibleEvent *event, void *user_data);
49 static void timing_test_event (const AccessibleEvent *event, void *user_data);
50 static SPIBoolean report_mouse_event  (const AccessibleDeviceEvent *event, void *user_data);
51
52 static AccessibleEventListener *generic_listener;
53 static AccessibleEventListener *specific_listener;
54 static AccessibleEventListener *bounds_listener;
55 static AccessibleEventListener *detail1_listener;
56 static AccessibleEventListener *test_listener;
57 static AccessibleEventListener *text_listener;
58 static AccessibleEventListener *caret_listener;
59 static AccessibleEventListener *text_selection_listener;
60 static AccessibleEventListener *active_descendant_changed_listener;
61 static AccessibleEventListener *children_changed_listener;
62 static AccessibleEventListener *name_changed_listener;
63 static AccessibleEventListener *description_changed_listener;
64 static AccessibleEventListener *parent_changed_listener;
65 static AccessibleEventListener *window_listener;
66 static AccessibleEventListener *table_summary_listener;
67 static AccessibleEventListener *table_header_listener;
68 static AccessibleEventListener *table_caption_listener;
69 static AccessibleEventListener *table_row_description_listener;
70 static AccessibleEventListener *table_column_description_listener;
71 static AccessibleDeviceListener *mouse_device_listener;
72 static gint n_elements_traversed = 0;
73 static GTimer *timer;
74
75 static gboolean report_mouse_events = TRUE;
76
77 void 
78 usage_and_exit( void )
79 {
80   g_print("\nUsage: event-listener-test [-h] [-m]\n");
81   g_print("       -h    : prints this usage message.\n");
82   g_print("       -m    : disable mouse event reporting.\n\n");
83
84   exit( 1 );
85 }
86
87 int
88 main (int argc, char **argv)
89 {
90   int c;
91
92   /* Parse Command-line */
93   if ( argc > 1 ) {
94       while ( ( c = getopt( argc, argv, "hm")) != EOF ) {
95           switch( c ) {
96               case 'm':
97                   report_mouse_events = FALSE;
98                   break;
99               default:
100                   usage_and_exit();
101                   break;
102           }
103       }
104       if ( optind < argc ) {
105           usage_and_exit();
106       }
107   }
108
109   fprintf (stderr, "RUNNING\n");
110
111   SPI_init ();
112
113   generic_listener = SPI_createAccessibleEventListener (
114           report_event, NULL); 
115   specific_listener = SPI_createAccessibleEventListener (
116           report_detail_event, NULL); 
117   bounds_listener = SPI_createAccessibleEventListener (
118           report_bounds_event, NULL);
119   text_listener = SPI_createAccessibleEventListener (
120           report_text_event, NULL);
121   caret_listener = SPI_createAccessibleEventListener (
122           report_caret_event, NULL);
123   text_selection_listener = SPI_createAccessibleEventListener (
124           report_text_selection_event, NULL);
125   active_descendant_changed_listener = SPI_createAccessibleEventListener (
126           report_active_descendant_changed_event, NULL);
127   children_changed_listener = SPI_createAccessibleEventListener (
128           report_children_changed_event, NULL);
129   name_changed_listener = SPI_createAccessibleEventListener (
130           report_name_changed_event, NULL);
131   description_changed_listener = SPI_createAccessibleEventListener (
132           report_description_changed_event, NULL);
133   parent_changed_listener = SPI_createAccessibleEventListener (
134           report_parent_changed_event, NULL);
135   window_listener = SPI_createAccessibleEventListener (
136           report_window_event, NULL);
137   table_summary_listener = SPI_createAccessibleEventListener (
138           report_table_summary_event, NULL);
139   table_header_listener = SPI_createAccessibleEventListener (
140           report_table_header_event, NULL);
141   table_caption_listener = SPI_createAccessibleEventListener (
142           report_table_caption_event, NULL);
143   table_row_description_listener = SPI_createAccessibleEventListener (
144           report_table_row_description_event, NULL);
145   table_column_description_listener = SPI_createAccessibleEventListener (
146           report_table_column_description_event, NULL);
147   test_listener = SPI_createAccessibleEventListener (
148           timing_test_event, NULL);
149   mouse_device_listener = SPI_createAccessibleDeviceListener (
150           report_mouse_event, NULL);
151   detail1_listener = SPI_createAccessibleEventListener (
152           report_detail1_event, NULL); 
153
154   SPI_registerGlobalEventListener (generic_listener,
155                                    "focus:");
156   if ( report_mouse_events ) {
157       SPI_registerGlobalEventListener (specific_listener,
158                                        "mouse:rel");
159       SPI_registerGlobalEventListener (specific_listener,
160                                        "mouse:button");
161       SPI_registerGlobalEventListener (specific_listener,
162                                        "mouse:abs");
163   }
164   SPI_registerDeviceEventListener (mouse_device_listener, 
165                                    SPI_BUTTON_PRESSED | SPI_BUTTON_RELEASED,
166                                    NULL);
167   SPI_registerGlobalEventListener (specific_listener,
168                                    "keyboard:modifiers");
169
170   SPI_registerGlobalEventListener (generic_listener,
171                                    "object:property-change");
172   SPI_registerGlobalEventListener (name_changed_listener,
173                                    "object:property-change:accessible-name");
174   SPI_registerGlobalEventListener (description_changed_listener,
175                                    "object:property-change:accessible-description");
176   SPI_registerGlobalEventListener (parent_changed_listener,
177                                    "object:property-change:accessible-parent");
178   SPI_registerGlobalEventListener (generic_listener,
179                                    "object:state-changed"); 
180 /*  SPI_registerGlobalEventListener (specific_listener,
181     "object:state-changed:focused"); */
182   SPI_registerGlobalEventListener (generic_listener,
183                                    "object:selection-changed"); 
184
185   SPI_registerGlobalEventListener (children_changed_listener,
186                                    "object:children-changed"); 
187   SPI_registerGlobalEventListener (active_descendant_changed_listener,
188                                    "object:active-descendant-changed"); 
189   SPI_registerGlobalEventListener (generic_listener,
190                                    "object:visible-data-changed"); 
191   SPI_registerGlobalEventListener (text_selection_listener,
192                                    "object:text-selection-changed"); 
193   SPI_registerGlobalEventListener (caret_listener,
194                                    "object:text-caret-moved"); 
195   SPI_registerGlobalEventListener (text_listener,
196                                    "object:text-changed"); 
197   SPI_registerGlobalEventListener (generic_listener,
198                                    "object:column-inserted"); 
199   SPI_registerGlobalEventListener (generic_listener,
200                                    "object:row-inserted"); 
201   SPI_registerGlobalEventListener (generic_listener,
202                                    "object:column-reordered"); 
203   SPI_registerGlobalEventListener (generic_listener,
204                                    "object:row-reordered"); 
205   SPI_registerGlobalEventListener (generic_listener,
206                                    "object:column-deleted"); 
207   SPI_registerGlobalEventListener (generic_listener,
208                                    "object:row-deleted"); 
209   SPI_registerGlobalEventListener (generic_listener,
210                                    "object:model-changed"); 
211   SPI_registerGlobalEventListener (detail1_listener,
212                                    "object:link-selected"); 
213 #if 0
214   SPI_registerGlobalEventListener (bounds_listener,
215                                    "object:bounds-changed");
216 #endif
217   SPI_registerGlobalEventListener (window_listener,
218                                    "window:minimize");
219   SPI_registerGlobalEventListener (window_listener,
220                                    "window:maximize");
221   SPI_registerGlobalEventListener (window_listener,
222                                    "window:restore");
223   SPI_registerGlobalEventListener (window_listener,
224                                    "window:activate");
225   SPI_registerGlobalEventListener (window_listener,
226                                    "window:create");
227   SPI_registerGlobalEventListener (window_listener,
228                                    "window:deactivate");
229   SPI_registerGlobalEventListener (window_listener,
230                                    "window:close");
231   SPI_registerGlobalEventListener (window_listener,
232                                    "window:lower");
233   SPI_registerGlobalEventListener (window_listener,
234                                    "window:raise");
235   SPI_registerGlobalEventListener (window_listener,
236                                    "window:resize");
237   SPI_registerGlobalEventListener (window_listener,
238                                    "window:shade");
239   SPI_registerGlobalEventListener (window_listener,
240                                    "window:unshade");
241   SPI_registerGlobalEventListener (table_summary_listener,
242                                    "object:property-change:accessible-table-summary");
243   SPI_registerGlobalEventListener (table_header_listener,
244                                    "object:property-change:accessible-table-row-header");
245   SPI_registerGlobalEventListener (table_header_listener,
246                                    "object:property-change:accessible-table-column-header");
247   SPI_registerGlobalEventListener (table_summary_listener,
248                                    "object:property-change:accessible-table-summary");
249   SPI_registerGlobalEventListener (table_row_description_listener,
250                                    "object:property-change:accessible-table-row-description");
251   SPI_registerGlobalEventListener (table_column_description_listener,
252                                    "object:property-change:accessible-table-column-description");
253   SPI_registerGlobalEventListener (test_listener,
254                                    "object:test");
255 #ifdef NOT_YET_IMPLEMENTED
256   /* event below possibly should just be property change? */
257   SPI_registerGlobalEventListener (generic_listener,
258                                    "window:restyle"); 
259   SPI_registerGlobalEventListener (generic_listener,
260                                    "window:desktop-create");
261   SPI_registerGlobalEventListener (generic_listener,
262                                    "window:desktop-destroy");
263 #endif
264   
265   timer = g_timer_new ();
266   traverse_accessible_tree (SPI_getDesktop (0));
267   g_print ("Time for first traversal of %d elements: %lf\n", 
268            n_elements_traversed,
269            g_timer_elapsed (timer, NULL));
270   g_timer_start (timer);
271   traverse_accessible_tree (SPI_getDesktop (0));
272   g_timer_stop (timer);
273   g_print ("Time for subsequent traversal %f\n", g_timer_elapsed (timer, NULL));
274   g_print ("[%f elements/sec, %f SPI calls/sec]\n", 
275         n_elements_traversed/g_timer_elapsed(timer, NULL),
276         (n_elements_traversed*8+1)/g_timer_elapsed(timer, NULL));
277   g_timer_reset (timer);
278   SPI_event_main ();
279
280   putenv ("AT_BRIDGE_SHUTDOWN=1");
281
282   /*
283    * TODO: Add a key event listener that calls test_exit, to
284    * deregister and cleanup appropriately.
285    */
286
287   return SPI_exit ();
288 }
289
290 static void
291 traverse_accessible_tree (Accessible *accessible)
292 {
293         int n_children;
294         int i;
295         char *name;
296         char *role_name;
297         Accessible *child;
298         
299         n_elements_traversed++;
300         name = Accessible_getName (accessible);
301         role_name = Accessible_getRoleName (accessible);
302 #ifdef VERBOSE
303         fprintf (stdout, "[%s] \"%s\"\n",
304                  role_name, name);
305 #endif
306         SPI_freeString (name);
307         SPI_freeString (role_name);
308         n_children = Accessible_getChildCount (accessible);
309         if (!Accessible_isTable (accessible)) 
310         {
311                 for (i = 0; i < n_children; ++i)
312                 {
313                         child = Accessible_getChildAtIndex (accessible, i);
314                         traverse_accessible_tree (child);
315                         Accessible_unref (child);
316                 }
317         }
318 }
319
320 void
321 report_event (const AccessibleEvent *event, void *user_data)
322 {
323   static long count = 0;
324   char *s = Accessible_getName (event->source);
325   fprintf (stderr, "%s %s\n", event->type, s);
326   if (s) SPI_freeString (s);
327   if (count == 0) {
328           g_timer_reset (timer);
329           g_timer_start (timer);
330   }
331   ++count;
332   if ((count % 100) == 0) {
333           g_print ("%ld events received, %f events/sec\n",
334                    count,
335                    count/g_timer_elapsed(timer, NULL));
336   }
337
338   /* check for Table interface - if present, query selections */
339   if (Accessible_isTable (event->source)) 
340   {
341       gint n_selected_rows = 0;
342       gint n_selected_cols = 0;
343       long int *rows, *cols;
344       AccessibleTable *table = Accessible_getTable (event->source);
345
346       n_selected_rows = AccessibleTable_getSelectedRows (table, &rows);
347       n_selected_cols  = AccessibleTable_getSelectedColumns (table, &cols);
348
349       g_print ("TABLE interface: selectedRows=%d, selectedCols = %d\n",
350                n_selected_rows, n_selected_cols);
351   }
352 }
353
354 void
355 report_caret_event (const AccessibleEvent *event, void *user_data)
356 {
357   char *s = Accessible_getName (event->source);
358   long int start, end, offset, line_start_begin;
359   long int line_start_end, line_end_begin, line_end_end;
360
361   AccessibleText *text = Accessible_getText (event->source);
362   offset = event->detail1;
363   AccessibleText_getTextAtOffset (text, offset, 
364                                   SPI_TEXT_BOUNDARY_SENTENCE_START,
365                                   &start, &end);
366   fprintf (stderr, 
367            "caret event from %s %s: offset %ld, SENTENCE_START offsets start=%ld, end=%ld\n", 
368            event->type, s, offset, start, end);
369   AccessibleText_getTextAtOffset (text, offset, 
370                                   SPI_TEXT_BOUNDARY_SENTENCE_END,
371                                   &start, &end);
372   AccessibleText_getTextAtOffset (text, offset, 
373                                   SPI_TEXT_BOUNDARY_LINE_START,
374                                   &line_start_begin, &line_start_end);
375   AccessibleText_getTextAtOffset (text, offset, 
376                                   SPI_TEXT_BOUNDARY_LINE_END,
377                                   &line_end_begin, &line_end_end);
378   fprintf (stderr, 
379            "SENTENCE_END: %ld - %ld; LINE_START: %ld - %ld; LINE_END: %ld - %ld\n", 
380            start, end, line_start_begin, line_start_end,
381            line_end_begin, line_end_end);
382
383   AccessibleText_getTextAtOffset (text, offset, 
384                                   SPI_TEXT_BOUNDARY_WORD_START,
385                                   &line_start_begin, &line_start_end);
386   AccessibleText_getTextAtOffset (text, offset, 
387                                   SPI_TEXT_BOUNDARY_WORD_END,
388                                   &line_end_begin, &line_end_end);
389   fprintf (stderr, 
390            "WORD_START: %ld - %ld; WORD_END: %ld - %ld\n", 
391            line_start_begin, line_start_end,
392            line_end_begin, line_end_end);
393
394   if (s) SPI_freeString (s);
395 }
396
397 void
398 report_detail_event (const AccessibleEvent *event, void *user_data)
399 {
400   char *s = Accessible_getName (event->source);
401   fprintf (stderr, "(detail) %s %s %ld %ld\n", event->type, s,
402            event->detail1, event->detail2);
403   if (s) SPI_freeString (s);
404 }
405
406 void
407 report_detail1_event (const AccessibleEvent *event, void *user_data)
408 {
409   char *s = Accessible_getName (event->source);
410   fprintf (stderr, "(detail) %s %s %ld\n", event->type, s,
411            event->detail1);
412   if (s) SPI_freeString (s);
413 }
414
415 void
416 report_bounds_event (const AccessibleEvent *event, void *user_data)
417 {
418   char *s = Accessible_getName (event->source);
419   SPIRect *bounds = AccessibleBoundsChangedEvent_getNewBounds (event);
420   if (!bounds) fprintf (stderr, "bounds-changed event with no bounds?\n");
421   fprintf (stderr, "(bounds-changed) %s %s %ld,%ld - %ld,%ld\n", event->type, s,
422            bounds->x, bounds->y, bounds->x + bounds->width, bounds->y + bounds->height);
423   SPI_freeRect (bounds);
424   if (s) SPI_freeString (s);
425 }
426
427 void
428 report_text_event (const AccessibleEvent *event, void *user_data)
429 {
430   char *s = Accessible_getName (event->source);
431   fprintf (stderr, "(detail) %s %s %ld %ld\n", event->type, s,
432            event->detail1, event->detail2);
433   SPI_freeString (s);
434   s = AccessibleTextChangedEvent_getChangeString (event);
435   fprintf (stderr, "context string %s\n", (s) ? s : "<nil>");
436   if (s) SPI_freeString (s);
437 }
438
439 void
440 report_text_selection_event (const AccessibleEvent *event, void *user_data)
441 {
442   char *s = Accessible_getName (event->source);
443   fprintf (stderr, "(detail) %s %s %ld %ld\n", event->type, s,
444            event->detail1, event->detail2);
445   SPI_freeString (s);
446   s = AccessibleTextSelectionChangedEvent_getSelectionString (event);
447   fprintf (stderr, "context string %s\n", (s) ? s : "<nil>");
448   SPI_freeString (s);
449 }
450
451 void
452 report_active_descendant_changed_event (const AccessibleEvent *event, void *user_data)
453 {
454   char *s = Accessible_getName (event->source);
455   char *s1;
456   Accessible *ao;
457
458   ao = AccessibleActiveDescendantChangedEvent_getActiveDescendant (event);
459   s1 = Accessible_getName (ao);
460   fprintf (stderr, "(detail) %s parent: %s child: %s %ld %ld\n", event->type, 
461            s ? s : "<null>", s1 ? s1 : "<null>",
462            event->detail1, event->detail2);
463   SPI_freeString (s);
464   SPI_freeString (s1);
465   Accessible_unref (ao);
466 }
467 void
468 report_children_changed_event (const AccessibleEvent *event, void *user_data)
469 {
470   char *s = Accessible_getName (event->source);
471   char *s1 = NULL, *s2, *s3 = NULL;
472   Accessible *ao;
473
474   ao = AccessibleChildChangedEvent_getChildAccessible (event);
475   if (ao) s1 = Accessible_getName (ao);
476   s2 = Accessible_getRoleName (event->source);
477   if (ao) s3 = Accessible_getRoleName (ao);
478   fprintf (stderr, "(detail) %s parent: %s [%s] child: %s [%s] %ld %ld\n", 
479            event->type, 
480            s ? s : "<null>", 
481            s2,
482            s1 ? s1 : "<null>",
483            s3 ? s3 : "<null>",
484            event->detail1, event->detail2);
485   SPI_freeString (s);
486   SPI_freeString (s1);
487   SPI_freeString (s2);
488   SPI_freeString (s3);
489   Accessible_unref (ao);
490 }
491
492 void
493 report_name_changed_event (const AccessibleEvent *event, void *user_data)
494 {
495   char *s = Accessible_getName (event->source);
496   fprintf (stderr, "(detail) %s %s %ld %ld\n", event->type, s,
497            event->detail1, event->detail2);
498   SPI_freeString (s);
499   s = AccessibleNameChangedEvent_getNameString (event);
500   fprintf (stderr, "context string %s\n", (s) ? s : "<nil>");
501   SPI_freeString (s);
502 }
503
504 void
505 report_description_changed_event (const AccessibleEvent *event, void *user_data)
506 {
507   char *s = Accessible_getName (event->source);
508   fprintf (stderr, "(detail) %s %s %ld %ld\n", event->type, s,
509            event->detail1, event->detail2);
510   SPI_freeString (s);
511   s = AccessibleDescriptionChangedEvent_getDescriptionString (event);
512   fprintf (stderr, "context string %s\n", (s) ? s : "<nil>");
513   SPI_freeString (s);
514 }
515
516 void
517 report_parent_changed_event (const AccessibleEvent *event, void *user_data)
518 {
519   char *s = Accessible_getName (event->source);
520   char *s1;
521   Accessible *ao;
522
523   ao = AccessibleParentChangedEvent_getParentAccessible (event);
524   s1 = Accessible_getName (ao);
525   fprintf (stderr, "(detail) %s parent: %s child: %s %ld %ld\n", event->type, 
526            s ? s : "<null>", s1 ? s1 : "<null>",
527            event->detail1, event->detail2);
528   SPI_freeString (s);
529   SPI_freeString (s1);
530   Accessible_unref (ao);
531 }
532
533 void
534 report_window_event (const AccessibleEvent *event, void *user_data)
535 {
536   char *s = Accessible_getName (event->source);
537   fprintf (stderr, "(detail) %s %s %ld %ld\n", event->type, s,
538            event->detail1, event->detail2);
539   SPI_freeString (s);
540   s = AccessibleWindowEvent_getTitleString (event);
541   fprintf (stderr, "context string %s\n", (s) ? s : "<nil>");
542   SPI_freeString (s);
543 }
544
545 void
546 report_table_summary_event (const AccessibleEvent *event, void *user_data)
547 {
548   char *s = Accessible_getName (event->source);
549   char *s1;
550   Accessible *ao;
551
552   ao = AccessibleTableSummaryChangedEvent_getSummaryAccessible (event);
553   s1 = Accessible_getName (ao);
554   fprintf (stderr, "(detail) %s parent: %s child: %s %ld %ld\n", event->type, 
555            s ? s : "<null>", s1 ? s1 : "<null>",
556            event->detail1, event->detail2);
557   SPI_freeString (s);
558   SPI_freeString (s1);
559   Accessible_unref (ao);
560 }
561
562 void
563 report_table_header_event (const AccessibleEvent *event, void *user_data)
564 {
565   char *s = Accessible_getName (event->source);
566   char *s1;
567   Accessible *ao;
568
569   ao = AccessibleTableHeaderChangedEvent_getHeaderAccessible (event);
570   s1 = Accessible_getName (ao);
571   fprintf (stderr, "(detail) %s parent: %s child: %s %ld %ld\n", event->type, 
572            s ? s : "<null>", s1 ? s1 : "<null>",
573            event->detail1, event->detail2);
574   SPI_freeString (s);
575   SPI_freeString (s1);
576   Accessible_unref (ao);
577 }
578
579 void
580 report_table_caption_event (const AccessibleEvent *event, void *user_data)
581 {
582   char *s = Accessible_getName (event->source);
583   fprintf (stderr, "(detail) %s %s %ld %ld\n", event->type, s,
584            event->detail1, event->detail2);
585   SPI_freeString (s);
586   s = AccessibleTableCaptionChangedEvent_getCaptionString (event);
587   fprintf (stderr, "context string %s\n", (s) ? s : "<nil>");
588   SPI_freeString (s);
589 }
590
591 void
592 report_table_row_description_event (const AccessibleEvent *event, void *user_data)
593 {
594   char *s = Accessible_getName (event->source);
595   fprintf (stderr, "(detail) %s %s %ld %ld\n", event->type, s,
596            event->detail1, event->detail2);
597   SPI_freeString (s);
598   s = AccessibleTableRowDescriptionChangedEvent_getDescriptionString (event);
599   fprintf (stderr, "context string %s\n", (s) ? s : "<nil>");
600   SPI_freeString (s);
601 }
602
603 void
604 report_table_column_description_event (const AccessibleEvent *event, void *user_data)
605 {
606   char *s = Accessible_getName (event->source);
607   fprintf (stderr, "(detail) %s %s %ld %ld\n", event->type, s,
608            event->detail1, event->detail2);
609   SPI_freeString (s);
610   s = AccessibleTableColumnDescriptionChangedEvent_getDescriptionString (event);
611   fprintf (stderr, "context string %s\n", (s) ? s : "<nil>");
612   SPI_freeString (s);
613 }
614
615 SPIBoolean
616 report_mouse_event (const AccessibleDeviceEvent *event, void *user_data)
617 {
618   fprintf (stderr, "mouse event %ld %d %x %x\n", 
619            event->keyID, 
620            (int) event->keycode,
621            (unsigned) event->type,
622            (unsigned) event->modifiers);
623   return FALSE;
624 }
625
626 void
627 timing_test_event (const AccessibleEvent *event, void *user_data)
628 {
629         static long count = 0;
630         if (count == 0) g_timer_start (timer);
631         ++count;
632         if ((count % 500) == 0) {
633                 g_print ("%ld events received, %f events/sec\n",
634                          count,
635                          count/g_timer_elapsed(timer, NULL));
636         }
637 }
638
639 void
640 test_exit (void)
641 {
642   SPI_deregisterGlobalEventListenerAll (generic_listener);
643   AccessibleEventListener_unref (generic_listener);
644   SPI_deregisterGlobalEventListenerAll (specific_listener);
645   AccessibleEventListener_unref (specific_listener);
646 }