2003-04-02 Padraig O'Briain <padraig.obriain@sun.com>
[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 <stdlib.h>
25 #include <unistd.h>
26 #include "../cspi/spi-private.h" /* A hack for now */
27
28 static void traverse_accessible_tree (Accessible *accessible);
29
30 static void report_event  (const AccessibleEvent *event, void *user_data);
31 static void report_detail_event  (const AccessibleEvent *event, void *user_data);
32 static void report_detail1_event  (const AccessibleEvent *event, void *user_data);
33 static void report_text_event  (const AccessibleEvent *event, void *user_data);
34 static void report_text_selection_event  (const AccessibleEvent *event, void *user_data);
35 static void report_active_descendant_event  (const AccessibleEvent *event, void *user_data);
36 static void report_children_changed_event (const AccessibleEvent *event, void *user_data);
37 static void report_name_changed_event (const AccessibleEvent *event, void *user_data);
38 static void report_description_changed_event (const AccessibleEvent *event, void *user_data);
39 static void report_parent_changed_event (const AccessibleEvent *event, void *user_data);
40 static void report_window_event  (const AccessibleEvent *event, void *user_data);
41 static void report_table_summary_event  (const AccessibleEvent *event, void *user_data);
42 static void report_table_header_event  (const AccessibleEvent *event, void *user_data);
43 static void report_table_caption_event  (const AccessibleEvent *event, void *user_data);
44 static void report_table_row_description_event  (const AccessibleEvent *event, void *user_data);
45 static void report_table_column_description_event  (const AccessibleEvent *event, void *user_data);
46 static void timing_test_event (const AccessibleEvent *event, void *user_data);
47 static SPIBoolean report_mouse_event  (const AccessibleDeviceEvent *event, void *user_data);
48
49 static AccessibleEventListener *generic_listener;
50 static AccessibleEventListener *specific_listener;
51 static AccessibleEventListener *detail1_listener;
52 static AccessibleEventListener *test_listener;
53 static AccessibleEventListener *text_listener;
54 static AccessibleEventListener *text_selection_listener;
55 static AccessibleEventListener *active_descendant_listener;
56 static AccessibleEventListener *children_changed_listener;
57 static AccessibleEventListener *name_changed_listener;
58 static AccessibleEventListener *description_changed_listener;
59 static AccessibleEventListener *parent_changed_listener;
60 static AccessibleEventListener *window_listener;
61 static AccessibleEventListener *table_summary_listener;
62 static AccessibleEventListener *table_header_listener;
63 static AccessibleEventListener *table_caption_listener;
64 static AccessibleEventListener *table_row_description_listener;
65 static AccessibleEventListener *table_column_description_listener;
66 static AccessibleDeviceListener *mouse_device_listener;
67 static gint n_elements_traversed = 0;
68 static GTimer *timer;
69
70 static gboolean report_mouse_events = TRUE;
71
72 void 
73 usage_and_exit( void )
74 {
75   g_print("\nUsage: event-listener-test [-h] [-m]\n");
76   g_print("       -h    : prints this usage message.\n");
77   g_print("       -m    : disable mouse event reporting.\n\n");
78
79   exit( 1 );
80 }
81
82 int
83 main (int argc, char **argv)
84 {
85   int i, j, c;
86   int n_desktops;
87   int n_apps;
88   char *s;
89   gdouble elapsed_time;
90   Accessible *desktop;
91   Accessible *application;
92   const char *modules;
93
94   /* Parse Command-line */
95   if ( argc > 1 ) {
96       while ( ( c = getopt( argc, argv, "hm")) != EOF ) {
97           switch( c ) {
98               case 'm':
99                   report_mouse_events = FALSE;
100                   break;
101               default:
102                   usage_and_exit();
103                   break;
104           }
105       }
106       if ( optind < argc ) {
107           usage_and_exit();
108       }
109   }
110
111   fprintf (stderr, "RUNNING\n");
112
113   SPI_init ();
114
115   generic_listener = SPI_createAccessibleEventListener (
116           report_event, NULL); 
117   specific_listener = SPI_createAccessibleEventListener (
118           report_detail_event, NULL); 
119   text_listener = SPI_createAccessibleEventListener (
120           report_text_event, NULL);
121   text_selection_listener = SPI_createAccessibleEventListener (
122           report_text_selection_event, NULL);
123   active_descendant_listener = SPI_createAccessibleEventListener (
124           report_active_descendant_event, NULL);
125   children_changed_listener = SPI_createAccessibleEventListener (
126           report_children_changed_event, NULL);
127   name_changed_listener = SPI_createAccessibleEventListener (
128           report_name_changed_event, NULL);
129   description_changed_listener = SPI_createAccessibleEventListener (
130           report_description_changed_event, NULL);
131   parent_changed_listener = SPI_createAccessibleEventListener (
132           report_parent_changed_event, NULL);
133   window_listener = SPI_createAccessibleEventListener (
134           report_window_event, NULL);
135   table_summary_listener = SPI_createAccessibleEventListener (
136           report_table_summary_event, NULL);
137   table_header_listener = SPI_createAccessibleEventListener (
138           report_table_header_event, NULL);
139   table_caption_listener = SPI_createAccessibleEventListener (
140           report_table_caption_event, NULL);
141   table_row_description_listener = SPI_createAccessibleEventListener (
142           report_table_row_description_event, NULL);
143   table_column_description_listener = SPI_createAccessibleEventListener (
144           report_table_column_description_event, NULL);
145   test_listener = SPI_createAccessibleEventListener (
146           timing_test_event, NULL);
147   mouse_device_listener = SPI_createAccessibleDeviceListener (
148           report_mouse_event, NULL);
149   detail1_listener = SPI_createAccessibleEventListener (
150           report_detail1_event, NULL); 
151
152   SPI_registerGlobalEventListener (generic_listener,
153                                    "focus:");
154   if ( report_mouse_events ) {
155       SPI_registerGlobalEventListener (specific_listener,
156                                        "mouse:rel");
157       SPI_registerGlobalEventListener (specific_listener,
158                                        "mouse:button");
159       SPI_registerGlobalEventListener (specific_listener,
160                                        "mouse:abs");
161   }
162   SPI_registerDeviceEventListener (mouse_device_listener, 
163                                    SPI_BUTTON_PRESSED | SPI_BUTTON_RELEASED,
164                                    NULL);
165   SPI_registerGlobalEventListener (specific_listener,
166                                    "keyboard:modifiers");
167   SPI_registerGlobalEventListener (generic_listener,
168                                    "object:property-change");
169   SPI_registerGlobalEventListener (name_changed_listener,
170                                    "object:property-change:accessible-name");
171   SPI_registerGlobalEventListener (description_changed_listener,
172                                    "object:property-change:accessible-description");
173   SPI_registerGlobalEventListener (parent_changed_listener,
174                                    "object:property-change:accessible-parent");
175   SPI_registerGlobalEventListener (generic_listener,
176                                    "object:state-changed"); 
177 /*  SPI_registerGlobalEventListener (specific_listener,
178     "object:state-changed:focused"); */
179   SPI_registerGlobalEventListener (generic_listener,
180                                    "object:selection-changed"); 
181   SPI_registerGlobalEventListener (children_changed_listener,
182                                    "object:children-changed"); 
183   SPI_registerGlobalEventListener (active_descendant_listener,
184                                    "object:active-descendant"); 
185   SPI_registerGlobalEventListener (generic_listener,
186                                    "object:visible-data-changed"); 
187   SPI_registerGlobalEventListener (text_selection_listener,
188                                    "object:text-selection-changed"); 
189
190   SPI_registerGlobalEventListener (generic_listener,
191                                    "object:text-caret-moved"); 
192   SPI_registerGlobalEventListener (text_listener,
193                                    "object:text-changed"); 
194   SPI_registerGlobalEventListener (generic_listener,
195                                    "object:column-inserted"); 
196   SPI_registerGlobalEventListener (generic_listener,
197                                    "object:row-inserted"); 
198   SPI_registerGlobalEventListener (generic_listener,
199                                    "object:column-reordered"); 
200   SPI_registerGlobalEventListener (generic_listener,
201                                    "object:row-reordered"); 
202   SPI_registerGlobalEventListener (generic_listener,
203                                    "object:column-deleted"); 
204   SPI_registerGlobalEventListener (generic_listener,
205                                    "object:row-deleted"); 
206   SPI_registerGlobalEventListener (generic_listener,
207                                    "object:model-changed"); 
208   SPI_registerGlobalEventListener (detail1_listener,
209                                    "object:link-selected"); 
210   SPI_registerGlobalEventListener (window_listener,
211                                    "window:minimize");
212   SPI_registerGlobalEventListener (window_listener,
213                                    "window:maximize");
214   SPI_registerGlobalEventListener (window_listener,
215                                    "window:restore");
216   SPI_registerGlobalEventListener (window_listener,
217                                    "window:activate");
218   SPI_registerGlobalEventListener (window_listener,
219                                    "window:deactivate");
220   SPI_registerGlobalEventListener (window_listener,
221                                    "window:close");
222   SPI_registerGlobalEventListener (window_listener,
223                                    "window:lower");
224   SPI_registerGlobalEventListener (window_listener,
225                                    "window:raise");
226   SPI_registerGlobalEventListener (window_listener,
227                                    "window:resize");
228   SPI_registerGlobalEventListener (window_listener,
229                                    "window:shade");
230   SPI_registerGlobalEventListener (window_listener,
231                                    "window:unshade");
232   SPI_registerGlobalEventListener (table_summary_listener,
233                                    "object:property-change:accessible-table-summary");
234   SPI_registerGlobalEventListener (table_header_listener,
235                                    "object:property-change:accessible-table-row-header");
236   SPI_registerGlobalEventListener (table_header_listener,
237                                    "object:property-change:accessible-table-column-header");
238   SPI_registerGlobalEventListener (table_summary_listener,
239                                    "object:property-change:accessible-table-summary");
240   SPI_registerGlobalEventListener (table_row_description_listener,
241                                    "object:property-change:accessible-table-row-description");
242   SPI_registerGlobalEventListener (table_column_description_listener,
243                                    "object:property-change:accessible-table-column-description");
244   SPI_registerGlobalEventListener (test_listener,
245                                    "object:test");
246 #ifdef NOT_YET_IMPLEMENTED
247   /* event below possibly should just be property change? */
248   SPI_registerGlobalEventListener (generic_listener,
249                                    "window:restyle"); 
250   SPI_registerGlobalEventListener (generic_listener,
251                                    "window:desktop-create");
252   SPI_registerGlobalEventListener (generic_listener,
253                                    "window:desktop-destroy");
254 #endif
255   
256   timer = g_timer_new ();
257   traverse_accessible_tree (SPI_getDesktop (0));
258   g_print ("Time for first traversal of %d elements: %lf\n", 
259            n_elements_traversed,
260            g_timer_elapsed (timer, NULL));
261   g_timer_start (timer);
262   traverse_accessible_tree (SPI_getDesktop (0));
263   g_timer_stop (timer);
264   g_print ("Time for subsequent traversal %f\n", g_timer_elapsed (timer, NULL));
265   g_print ("[%f elements/sec, %f SPI calls/sec]\n", 
266         n_elements_traversed/g_timer_elapsed(timer, NULL),
267         (n_elements_traversed*8+1)/g_timer_elapsed(timer, NULL));
268   g_timer_reset (timer);
269   SPI_event_main ();
270
271   putenv ("AT_BRIDGE_SHUTDOWN=1");
272
273   /*
274    * TODO: Add a key event listener that calls test_exit, to
275    * deregister and cleanup appropriately.
276    */
277
278   return SPI_exit ();
279 }
280
281 static void
282 traverse_accessible_tree (Accessible *accessible)
283 {
284         int n_children;
285         int i;
286         char *name;
287         char *role_name;
288         Accessible *child;
289         
290         n_elements_traversed++;
291         name = Accessible_getName (accessible);
292         role_name = Accessible_getRoleName (accessible);
293 #ifdef VERBOSE
294         fprintf (stdout, "[%s] \"%s\"\n",
295                  role_name, name);
296 #endif
297         SPI_freeString (name);
298         SPI_freeString (role_name);
299         n_children = Accessible_getChildCount (accessible);
300         if (!Accessible_isTable (accessible)) 
301         {
302                 for (i = 0; i < n_children; ++i)
303                 {
304                         child = Accessible_getChildAtIndex (accessible, i);
305                         traverse_accessible_tree (child);
306                         Accessible_unref (child);
307                 }
308         }
309 }
310
311 void
312 report_event (const AccessibleEvent *event, void *user_data)
313 {
314   static long count = 0;
315   char *s = Accessible_getName (event->source);
316   fprintf (stderr, "%s %s\n", event->type, s);
317   if (s) SPI_freeString (s);
318   if (count == 0) {
319           g_timer_reset (timer);
320           g_timer_start (timer);
321   }
322   ++count;
323   if ((count % 100) == 0) {
324           g_print ("%d events received, %f events/sec\n",
325                    count,
326                    count/g_timer_elapsed(timer, NULL));
327   }
328 }
329
330 void
331 report_detail_event (const AccessibleEvent *event, void *user_data)
332 {
333   char *s = Accessible_getName (event->source);
334   fprintf (stderr, "(detail) %s %s %d %d\n", event->type, s,
335            event->detail1, event->detail2);
336   if (s) SPI_freeString (s);
337 }
338
339 void
340 report_detail1_event (const AccessibleEvent *event, void *user_data)
341 {
342   char *s = Accessible_getName (event->source);
343   fprintf (stderr, "(detail) %s %s %d\n", event->type, s,
344            event->detail1);
345   if (s) SPI_freeString (s);
346 }
347
348 void
349 report_text_event (const AccessibleEvent *event, void *user_data)
350 {
351   char *s = Accessible_getName (event->source);
352   fprintf (stderr, "(detail) %s %s %d %d\n", event->type, s,
353            event->detail1, event->detail2);
354   SPI_freeString (s);
355   s = AccessibleTextChangedEvent_getChangeString (event);
356   fprintf (stderr, "context string %s\n", (s) ? s : "<nil>");
357   SPI_freeString (s);
358 }
359
360 void
361 report_text_selection_event (const AccessibleEvent *event, void *user_data)
362 {
363   char *s = Accessible_getName (event->source);
364   fprintf (stderr, "(detail) %s %s %d %d\n", event->type, s,
365            event->detail1, event->detail2);
366   SPI_freeString (s);
367   s = AccessibleTextSelectionChangedEvent_getSelectionString (event);
368   fprintf (stderr, "context string %s\n", (s) ? s : "<nil>");
369   SPI_freeString (s);
370 }
371
372 void
373 report_active_descendant_event (const AccessibleEvent *event, void *user_data)
374 {
375   char *s = Accessible_getName (event->source);
376   char *s1;
377   Accessible *ao;
378
379   ao = AccessibleActiveDescendantChangedEvent_getActiveDescendant (event);
380   s1 = Accessible_getName (ao);
381   fprintf (stderr, "(detail) %s parent: %s child: %s %d %d\n", event->type, 
382            s ? s : "<null>", s1 ? s1 : "<null>",
383            event->detail1, event->detail2);
384   SPI_freeString (s);
385   SPI_freeString (s1);
386   Accessible_unref (ao);
387 }
388 void
389 report_children_changed_event (const AccessibleEvent *event, void *user_data)
390 {
391   char *s = Accessible_getName (event->source);
392   char *s1;
393   Accessible *ao;
394
395   ao = AccessibleChildChangedEvent_getChildAccessible (event);
396   s1 = Accessible_getName (ao);
397   fprintf (stderr, "(detail) %s parent: %s child: %s %d %d\n", event->type, 
398            s ? s : "<null>", s1 ? s1 : "<null>",
399            event->detail1, event->detail2);
400   SPI_freeString (s);
401   SPI_freeString (s1);
402   Accessible_unref (ao);
403 }
404
405 void
406 report_name_changed_event (const AccessibleEvent *event, void *user_data)
407 {
408   char *s = Accessible_getName (event->source);
409   fprintf (stderr, "(detail) %s %s %d %d\n", event->type, s,
410            event->detail1, event->detail2);
411   SPI_freeString (s);
412   s = AccessibleNameChangedEvent_getNameString (event);
413   fprintf (stderr, "context string %s\n", (s) ? s : "<nil>");
414   SPI_freeString (s);
415 }
416
417 void
418 report_description_changed_event (const AccessibleEvent *event, void *user_data)
419 {
420   char *s = Accessible_getName (event->source);
421   fprintf (stderr, "(detail) %s %s %d %d\n", event->type, s,
422            event->detail1, event->detail2);
423   SPI_freeString (s);
424   s = AccessibleDescriptionChangedEvent_getDescriptionString (event);
425   fprintf (stderr, "context string %s\n", (s) ? s : "<nil>");
426   SPI_freeString (s);
427 }
428
429 void
430 report_parent_changed_event (const AccessibleEvent *event, void *user_data)
431 {
432   char *s = Accessible_getName (event->source);
433   char *s1;
434   Accessible *ao;
435
436   ao = AccessibleParentChangedEvent_getParentAccessible (event);
437   s1 = Accessible_getName (ao);
438   fprintf (stderr, "(detail) %s parent: %s child: %s %d %d\n", event->type, 
439            s ? s : "<null>", s1 ? s1 : "<null>",
440            event->detail1, event->detail2);
441   SPI_freeString (s);
442   SPI_freeString (s1);
443   Accessible_unref (ao);
444 }
445
446 void
447 report_window_event (const AccessibleEvent *event, void *user_data)
448 {
449   char *s = Accessible_getName (event->source);
450   fprintf (stderr, "(detail) %s %s %d %d\n", event->type, s,
451            event->detail1, event->detail2);
452   SPI_freeString (s);
453   s = AccessibleWindowEvent_getTitleString (event);
454   fprintf (stderr, "context string %s\n", (s) ? s : "<nil>");
455   SPI_freeString (s);
456 }
457
458 void
459 report_table_summary_event (const AccessibleEvent *event, void *user_data)
460 {
461   char *s = Accessible_getName (event->source);
462   char *s1;
463   Accessible *ao;
464
465   ao = AccessibleTableSummaryChangedEvent_getSummaryAccessible (event);
466   s1 = Accessible_getName (ao);
467   fprintf (stderr, "(detail) %s parent: %s child: %s %d %d\n", event->type, 
468            s ? s : "<null>", s1 ? s1 : "<null>",
469            event->detail1, event->detail2);
470   SPI_freeString (s);
471   SPI_freeString (s1);
472   Accessible_unref (ao);
473 }
474
475 void
476 report_table_header_event (const AccessibleEvent *event, void *user_data)
477 {
478   char *s = Accessible_getName (event->source);
479   char *s1;
480   Accessible *ao;
481
482   ao = AccessibleTableHeaderChangedEvent_getHeaderAccessible (event);
483   s1 = Accessible_getName (ao);
484   fprintf (stderr, "(detail) %s parent: %s child: %s %d %d\n", event->type, 
485            s ? s : "<null>", s1 ? s1 : "<null>",
486            event->detail1, event->detail2);
487   SPI_freeString (s);
488   SPI_freeString (s1);
489   Accessible_unref (ao);
490 }
491
492 void
493 report_table_caption_event (const AccessibleEvent *event, void *user_data)
494 {
495   char *s = Accessible_getName (event->source);
496   fprintf (stderr, "(detail) %s %s %d %d\n", event->type, s,
497            event->detail1, event->detail2);
498   SPI_freeString (s);
499   s = AccessibleTableCaptionChangedEvent_getCaptionString (event);
500   fprintf (stderr, "context string %s\n", (s) ? s : "<nil>");
501   SPI_freeString (s);
502 }
503
504 void
505 report_table_row_description_event (const AccessibleEvent *event, void *user_data)
506 {
507   char *s = Accessible_getName (event->source);
508   fprintf (stderr, "(detail) %s %s %d %d\n", event->type, s,
509            event->detail1, event->detail2);
510   SPI_freeString (s);
511   s = AccessibleTableRowDescriptionChangedEvent_getDescriptionString (event);
512   fprintf (stderr, "context string %s\n", (s) ? s : "<nil>");
513   SPI_freeString (s);
514 }
515
516 void
517 report_table_column_description_event (const AccessibleEvent *event, void *user_data)
518 {
519   char *s = Accessible_getName (event->source);
520   fprintf (stderr, "(detail) %s %s %d %d\n", event->type, s,
521            event->detail1, event->detail2);
522   SPI_freeString (s);
523   s = AccessibleTableColumnDescriptionChangedEvent_getDescriptionString (event);
524   fprintf (stderr, "context string %s\n", (s) ? s : "<nil>");
525   SPI_freeString (s);
526 }
527
528 SPIBoolean
529 report_mouse_event (const AccessibleDeviceEvent *event, void *user_data)
530 {
531   fprintf (stderr, "mouse event %ld %d %x %x\n", 
532            event->keyID, 
533            (int) event->keycode,
534            (unsigned) event->type,
535            (unsigned) event->modifiers);
536   return FALSE;
537 }
538
539 void
540 timing_test_event (const AccessibleEvent *event, void *user_data)
541 {
542         static long count = 0;
543         if (count == 0) g_timer_start (timer);
544         ++count;
545         if ((count % 500) == 0) {
546                 g_print ("%d events received, %f events/sec\n",
547                          count,
548                          count/g_timer_elapsed(timer, NULL));
549         }
550 }
551
552 void
553 test_exit ()
554 {
555   SPI_deregisterGlobalEventListenerAll (generic_listener);
556   AccessibleEventListener_unref (generic_listener);
557   SPI_deregisterGlobalEventListenerAll (specific_listener);
558   AccessibleEventListener_unref (specific_listener);
559 }