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