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