2 * AT-SPI - Assistive Technology Service Provider Interface
3 * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
5 * Copyright 2001, 2002, 2003 Sun Microsystems Inc.,
6 * Copyright 2001, 2002, 2003 Ximian, Inc.
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.
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.
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.
27 #include "../cspi/spi-private.h" /* A hack for now */
29 static void traverse_accessible_tree (Accessible *accessible);
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);
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;
75 static gboolean report_mouse_events = TRUE;
78 usage_and_exit( void )
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");
88 main (int argc, char **argv)
92 /* Parse Command-line */
94 while ( ( c = getopt( argc, argv, "hm")) != EOF ) {
97 report_mouse_events = FALSE;
104 if ( optind < argc ) {
109 fprintf (stderr, "RUNNING\n");
113 generic_listener = SPI_createAccessibleEventListener (
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);
154 SPI_registerGlobalEventListener (generic_listener,
156 if ( report_mouse_events ) {
157 SPI_registerGlobalEventListener (specific_listener,
159 SPI_registerGlobalEventListener (specific_listener,
161 SPI_registerGlobalEventListener (specific_listener,
164 SPI_registerDeviceEventListener (mouse_device_listener,
165 SPI_BUTTON_PRESSED | SPI_BUTTON_RELEASED,
167 SPI_registerGlobalEventListener (specific_listener,
168 "keyboard:modifiers");
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");
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");
214 SPI_registerGlobalEventListener (bounds_listener,
215 "object:bounds-changed");
217 SPI_registerGlobalEventListener (window_listener,
219 SPI_registerGlobalEventListener (window_listener,
221 SPI_registerGlobalEventListener (window_listener,
223 SPI_registerGlobalEventListener (window_listener,
225 SPI_registerGlobalEventListener (window_listener,
227 SPI_registerGlobalEventListener (window_listener,
228 "window:deactivate");
229 SPI_registerGlobalEventListener (window_listener,
231 SPI_registerGlobalEventListener (window_listener,
233 SPI_registerGlobalEventListener (window_listener,
235 SPI_registerGlobalEventListener (window_listener,
237 SPI_registerGlobalEventListener (window_listener,
239 SPI_registerGlobalEventListener (window_listener,
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,
255 #ifdef NOT_YET_IMPLEMENTED
256 /* event below possibly should just be property change? */
257 SPI_registerGlobalEventListener (generic_listener,
259 SPI_registerGlobalEventListener (generic_listener,
260 "window:desktop-create");
261 SPI_registerGlobalEventListener (generic_listener,
262 "window:desktop-destroy");
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);
280 putenv ("AT_BRIDGE_SHUTDOWN=1");
283 * TODO: Add a key event listener that calls test_exit, to
284 * deregister and cleanup appropriately.
291 traverse_accessible_tree (Accessible *accessible)
299 n_elements_traversed++;
300 name = Accessible_getName (accessible);
301 role_name = Accessible_getRoleName (accessible);
303 fprintf (stdout, "[%s] \"%s\"\n",
306 SPI_freeString (name);
307 SPI_freeString (role_name);
308 n_children = Accessible_getChildCount (accessible);
309 if (!Accessible_isTable (accessible))
311 for (i = 0; i < n_children; ++i)
313 child = Accessible_getChildAtIndex (accessible, i);
314 traverse_accessible_tree (child);
315 Accessible_unref (child);
321 report_event (const AccessibleEvent *event, void *user_data)
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);
328 g_timer_reset (timer);
329 g_timer_start (timer);
332 if ((count % 100) == 0) {
333 g_print ("%ld events received, %f events/sec\n",
335 count/g_timer_elapsed(timer, NULL));
338 /* check for Table interface - if present, query selections */
339 if (Accessible_isTable (event->source))
341 gint n_selected_rows = 0;
342 gint n_selected_cols = 0;
343 long int *rows, *cols;
344 AccessibleTable *table = Accessible_getTable (event->source);
346 n_selected_rows = AccessibleTable_getSelectedRows (table, &rows);
347 n_selected_cols = AccessibleTable_getSelectedColumns (table, &cols);
349 g_print ("TABLE interface: selectedRows=%d, selectedCols = %d\n",
350 n_selected_rows, n_selected_cols);
355 report_caret_event (const AccessibleEvent *event, void *user_data)
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;
361 AccessibleText *text = Accessible_getText (event->source);
362 offset = event->detail1;
363 AccessibleText_getTextAtOffset (text, offset,
364 SPI_TEXT_BOUNDARY_SENTENCE_START,
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,
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);
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);
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);
390 "WORD_START: %ld - %ld; WORD_END: %ld - %ld\n",
391 line_start_begin, line_start_end,
392 line_end_begin, line_end_end);
394 if (s) SPI_freeString (s);
398 report_detail_event (const AccessibleEvent *event, void *user_data)
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);
407 report_detail1_event (const AccessibleEvent *event, void *user_data)
409 char *s = Accessible_getName (event->source);
410 fprintf (stderr, "(detail) %s %s %ld\n", event->type, s,
412 if (s) SPI_freeString (s);
416 report_bounds_event (const AccessibleEvent *event, void *user_data)
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);
428 report_text_event (const AccessibleEvent *event, void *user_data)
430 char *s = Accessible_getName (event->source);
431 fprintf (stderr, "(detail) %s %s %ld %ld\n", event->type, s,
432 event->detail1, event->detail2);
434 s = AccessibleTextChangedEvent_getChangeString (event);
435 fprintf (stderr, "context string %s\n", (s) ? s : "<nil>");
436 if (s) SPI_freeString (s);
440 report_text_selection_event (const AccessibleEvent *event, void *user_data)
442 char *s = Accessible_getName (event->source);
443 fprintf (stderr, "(detail) %s %s %ld %ld\n", event->type, s,
444 event->detail1, event->detail2);
446 s = AccessibleTextSelectionChangedEvent_getSelectionString (event);
447 fprintf (stderr, "context string %s\n", (s) ? s : "<nil>");
452 report_active_descendant_changed_event (const AccessibleEvent *event, void *user_data)
454 char *s = Accessible_getName (event->source);
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);
465 Accessible_unref (ao);
468 report_children_changed_event (const AccessibleEvent *event, void *user_data)
470 char *s = Accessible_getName (event->source);
471 char *s1 = NULL, *s2, *s3 = NULL;
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",
484 event->detail1, event->detail2);
489 Accessible_unref (ao);
493 report_name_changed_event (const AccessibleEvent *event, void *user_data)
495 char *s = Accessible_getName (event->source);
496 fprintf (stderr, "(detail) %s %s %ld %ld\n", event->type, s,
497 event->detail1, event->detail2);
499 s = AccessibleNameChangedEvent_getNameString (event);
500 fprintf (stderr, "context string %s\n", (s) ? s : "<nil>");
505 report_description_changed_event (const AccessibleEvent *event, void *user_data)
507 char *s = Accessible_getName (event->source);
508 fprintf (stderr, "(detail) %s %s %ld %ld\n", event->type, s,
509 event->detail1, event->detail2);
511 s = AccessibleDescriptionChangedEvent_getDescriptionString (event);
512 fprintf (stderr, "context string %s\n", (s) ? s : "<nil>");
517 report_parent_changed_event (const AccessibleEvent *event, void *user_data)
519 char *s = Accessible_getName (event->source);
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);
530 Accessible_unref (ao);
534 report_window_event (const AccessibleEvent *event, void *user_data)
536 char *s = Accessible_getName (event->source);
537 fprintf (stderr, "(detail) %s %s %ld %ld\n", event->type, s,
538 event->detail1, event->detail2);
540 s = AccessibleWindowEvent_getTitleString (event);
541 fprintf (stderr, "context string %s\n", (s) ? s : "<nil>");
546 report_table_summary_event (const AccessibleEvent *event, void *user_data)
548 char *s = Accessible_getName (event->source);
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);
559 Accessible_unref (ao);
563 report_table_header_event (const AccessibleEvent *event, void *user_data)
565 char *s = Accessible_getName (event->source);
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);
576 Accessible_unref (ao);
580 report_table_caption_event (const AccessibleEvent *event, void *user_data)
582 char *s = Accessible_getName (event->source);
583 fprintf (stderr, "(detail) %s %s %ld %ld\n", event->type, s,
584 event->detail1, event->detail2);
586 s = AccessibleTableCaptionChangedEvent_getCaptionString (event);
587 fprintf (stderr, "context string %s\n", (s) ? s : "<nil>");
592 report_table_row_description_event (const AccessibleEvent *event, void *user_data)
594 char *s = Accessible_getName (event->source);
595 fprintf (stderr, "(detail) %s %s %ld %ld\n", event->type, s,
596 event->detail1, event->detail2);
598 s = AccessibleTableRowDescriptionChangedEvent_getDescriptionString (event);
599 fprintf (stderr, "context string %s\n", (s) ? s : "<nil>");
604 report_table_column_description_event (const AccessibleEvent *event, void *user_data)
606 char *s = Accessible_getName (event->source);
607 fprintf (stderr, "(detail) %s %s %ld %ld\n", event->type, s,
608 event->detail1, event->detail2);
610 s = AccessibleTableColumnDescriptionChangedEvent_getDescriptionString (event);
611 fprintf (stderr, "context string %s\n", (s) ? s : "<nil>");
616 report_mouse_event (const AccessibleDeviceEvent *event, void *user_data)
618 fprintf (stderr, "mouse event %ld %d %x %x\n",
620 (int) event->keycode,
621 (unsigned) event->type,
622 (unsigned) event->modifiers);
627 timing_test_event (const AccessibleEvent *event, void *user_data)
629 static long count = 0;
630 if (count == 0) g_timer_start (timer);
632 if ((count % 500) == 0) {
633 g_print ("%ld events received, %f events/sec\n",
635 count/g_timer_elapsed(timer, NULL));
642 SPI_deregisterGlobalEventListenerAll (generic_listener);
643 AccessibleEventListener_unref (generic_listener);
644 SPI_deregisterGlobalEventListenerAll (specific_listener);
645 AccessibleEventListener_unref (specific_listener);