3 #define MAX_NAME_VALUE 20
8 #include <netinet/in.h>
9 #include <sys/socket.h>
54 /* GUI Information for the group */
59 GtkFrame *scroll_outer_frame;
82 GtkHBox *column1, *column2, *hbox;
102 /* Function prototypes */
106 static void _init_data(void);
107 static void _create_window(void);
108 static void _add_menu(GtkWidget ** menu, GtkWidget ** menuitem,
109 gchar * name, gboolean init_value, GCallback func);
110 static void _clear_tab(TabNumber tab_n);
111 static void _greyout_tab (GtkWidget *widget, gboolean is_sensitive);
112 static void _finished_group(TabNumber tab_n, gint group_num);
113 static gboolean _object_is_ours (AtkObject *aobject);
114 static void _create_event_watcher (void);
116 /* Mouse Watcher/Magnifier/Festival functions */
118 static gboolean _mouse_watcher (GSignalInvocationHint *ihint,
119 guint n_param_values,
120 const GValue *param_values,
122 static gboolean _button_watcher (GSignalInvocationHint *ihint,
123 guint n_param_values,
124 const GValue *param_values,
126 static void _send_to_magnifier (gint x, gint y, gint w, gint h);
127 static void _send_to_festival (const gchar * name,
128 const gchar * role_name, const gchar * accel);
129 static void _speak_caret_event (AtkObject * aobject);
130 static void _festival_say (const gchar * text);
131 static void _festival_write (const gchar * text, int fd);
132 static gint _festival_init (void);
134 /* Update functions */
136 static void _update_current_page(GtkNotebook *notebook, gpointer p,
138 static void _update(TabNumber top_tab, AtkObject *aobject);
140 /* Print functions */
142 static void _print_accessible (AtkObject *aobject);
144 static gint _print_object (AtkObject *aobject);
145 static gint _print_relation (AtkObject *aobject);
146 static gint _print_state (AtkObject *aobject);
148 static gint _print_action (AtkAction *aobject);
149 static gint _print_component (AtkComponent *aobject);
150 static gint _print_image (AtkImage *aobject);
151 static gint _print_selection (AtkSelection *aobject);
152 static gint _print_table (AtkTable *aobject);
153 static gint _print_text (AtkText *aobject);
154 static gint _print_text_attributes (AtkText *aobject);
155 static gint _print_value (AtkValue *aobject);
156 static void _print_value_type(gint group_num, gchar *type, GValue *value);
157 static gint _print_groupname(TabNumber tab_n, GroupId group_id,
158 const char *groupname);
159 static NameValue* _print_key_value(TabNumber tab_n, gint group_number,
160 const char *label, gpointer value, ValueType type);
161 static void _print_signal(AtkObject *aobject, FerretSignalType type,
162 const char *name, const char *info);
164 /* Data Access functions */
166 static GroupInfo* _get_group(TabInfo *tab, GroupId group_id,
167 const gchar *groupname);
168 void _get_group_scrolled(GroupInfo *group);
169 static NameValue* _get_name_value(GroupInfo *group, const gchar *label,
170 gpointer value, ValueType type);
172 /* Signal handlers */
174 static void _update_handlers(AtkObject *obj);
175 static void _notify_text_insert_handler (GObject *obj,
176 int position, int offset);
177 static void _notify_text_delete_handler (GObject *obj,
178 int position, int offset);
179 static void _notify_caret_handler (GObject *obj, int position);
180 static void _notify_table_row_inserted (GObject *obj,
181 gint start_offset, gint length);
182 static void _notify_table_column_inserted (GObject *obj,
183 gint start_offset, gint length);
184 static void _notify_table_row_deleted (GObject *obj,
185 gint start_offset, gint length);
186 static void _notify_table_column_deleted (GObject *obj,
187 gint start_offset, gint length);
188 static void _notify_table_row_reordered (GObject *obj);
189 static void _notify_table_column_reordered (GObject *obj);
190 static void _notify_object_child_added (GObject *obj,
191 gint index, AtkObject *child);
192 static void _notify_object_child_removed (GObject *obj,
193 gint index, AtkObject *child);
194 static void _notify_object_state_change (GObject *obj,
195 gchar *name, gboolean set);
197 /* Property handlers */
199 static void _property_change_handler (AtkObject *obj,
200 AtkPropertyValues *values);
202 /* Ferret GUI callbacks */
204 void _action_cb(GtkWidget *widget, gpointer *userdata);
205 void _toggle_terminal(GtkCheckMenuItem *checkmenuitem,
207 void _toggle_no_signals(GtkCheckMenuItem *checkmenuitem,
209 void _toggle_magnifier(GtkCheckMenuItem *checkmenuitem,
211 void _toggle_festival(GtkCheckMenuItem *checkmenuitem,
213 void _toggle_festival_terse(GtkCheckMenuItem *checkmenuitem,
215 void _toggle_trackmouse(GtkCheckMenuItem *checkmenuitem,
217 void _toggle_trackfocus(GtkCheckMenuItem *checkmenuitem,
220 /* Global variables */
221 static GtkNotebook *notebook;
222 static TabInfo *nbook_tabs[END_TABS];
223 static gint mouse_watcher_focus_id = -1;
224 static gint mouse_watcher_button_id = -1;
225 static gint focus_tracker_id = -1;
226 static gboolean use_magnifier = FALSE;
227 static gboolean use_festival = FALSE;
228 static gboolean track_mouse = FALSE;
229 static gboolean track_focus = TRUE;
230 static gboolean say_role = TRUE;
231 static gboolean say_accel = TRUE;
232 static gboolean display_ascii = FALSE;
233 static gboolean no_signals = FALSE;
234 static gint last_caret_offset = 0;
236 static AtkObject *last_object = NULL;
237 static GtkWidget *mainWindow = NULL;
238 static GtkWidget *vbox1 = NULL;
239 static GtkWidget *menu = NULL;
240 static GtkWidget *menutop = NULL;
241 static GtkWidget *menubar = NULL;
242 static GtkWidget *menuitem_terminal = NULL;
243 static GtkWidget *menuitem_no_signals = NULL;
244 static GtkWidget *menuitem_magnifier = NULL;
245 static GtkWidget *menuitem_festival = NULL;
246 static GtkWidget *menuitem_festival_terse = NULL;
247 static GtkWidget *menuitem_trackmouse = NULL;
248 static GtkWidget *menuitem_trackfocus = NULL;
250 #ifdef HAVE_SOCKADDR_UN_SUN_LEN
251 static struct sockaddr_un mag_server = { 0, AF_UNIX , "/tmp/magnifier_socket" };
252 static struct sockaddr_un client = { 0 , AF_UNIX, "/tmp/mag_client"};
254 static struct sockaddr_un mag_server = { AF_UNIX , "/tmp/magnifier_socket" };
255 static struct sockaddr_un client = { AF_UNIX, "/tmp/mag_client"};
258 /* GUI Information for the output window */
261 GtkWindow *outputWindow;
265 GtkWidget *textInsert;
270 _send_to_magnifier(gint x, gint y, gint w, gint h)
273 int length_msg G_GNUC_UNUSED;
276 sprintf (buff, "~5:%d,%d", x+w/2, y+h/2);
279 g_print ("sending magnifier: %s\n", buff);
282 #ifdef HAVE_SOCKADDR_UN_SUN_LEN
283 mag_server.sun_len = SUN_LEN(&mag_server);
284 client.sun_len = SUN_LEN(&client);
287 if((desc=socket(AF_UNIX,SOCK_STREAM,0)) == -1){
291 unlink("/tmp/mag_client");
293 if (bind(desc, (struct sockaddr*)&client, sizeof(client)) == -1)
299 if (connect(desc,(struct sockaddr*)&mag_server,sizeof(mag_server)) == -1)
305 length_msg = write(desc,buff,strlen(buff));
306 unlink("/tmp/mag_client");
310 static int _festival_init (void)
313 struct sockaddr_in name;
316 name.sin_family = AF_INET;
317 name.sin_port = htons (1314);
318 name.sin_addr.s_addr = htonl(INADDR_ANY);
319 fd = socket (PF_INET, SOCK_STREAM, 0);
321 while (connect(fd, (struct sockaddr *) &name, sizeof (name)) < 0) {
328 _festival_write ("(audio_mode'async)", fd);
332 static void _festival_say (const gchar *text)
338 const gchar *stretch;
340 fprintf (stderr, "saying %s\n", text);
344 fd = _festival_init ();
347 quoted = g_malloc(100+strlen(text)*2);
349 stretch = g_strdup (g_getenv ("FESTIVAL_STRETCH"));
350 if (!stretch) stretch = "0.75";
351 sprintf (prefix, "(audio_mode'shutup)\n (Parameter.set 'Duration_Stretch %s)\n (SayText \"", stretch);
353 strcpy(quoted, prefix);
354 p = quoted + strlen (prefix);
356 if ( *text == '\\' || *text == '"' )
364 _festival_write (quoted, fd);
370 static void _send_to_festival (const gchar *role_name,
371 const gchar *name, const gchar *accel)
374 int len = (strlen (role_name)+1 + strlen (name)+2 + 4 + strlen (accel)+2);
379 string = (gchar *) g_malloc (len * sizeof (gchar));
388 if (ch == '_') ch = ' ';
397 if (ch == '_') ch = ' ';
400 if ((say_accel) && (strlen (accel) > 0))
402 accel_name = (gchar *)accel;
403 if (strncmp (accel, "<C", 2) == 0)
405 accel_name = strncpy (accel_name, " control ", 9);
407 else if (strncmp (accel, " control", 5))
416 while (accel_name[j])
418 ch = accel_name[j++];
419 if (ch == '_') ch = ' ';
425 _festival_say (string);
429 static void _festival_write (const gchar *command_string, int fd)
437 n_bytes = write(fd, command_string, strlen(command_string));
438 g_assert (n_bytes == strlen(command_string));
441 static void _speak_caret_event (AtkObject *aobject)
444 gint caret_offset = atk_text_get_caret_offset (ATK_TEXT (aobject));
447 if (abs(caret_offset - last_caret_offset) > 1)
449 text = atk_text_get_text_at_offset (ATK_TEXT (aobject),
451 ATK_TEXT_BOUNDARY_LINE_START,
457 text = atk_text_get_text_before_offset (ATK_TEXT (aobject),
459 ATK_TEXT_BOUNDARY_CHAR,
463 _festival_say (text);
465 last_caret_offset = caret_offset;
469 _greyout_tab (GtkWidget *page_child, gboolean is_sensitive)
473 tab = gtk_notebook_get_tab_label (notebook, page_child);
475 gtk_widget_set_sensitive (GTK_WIDGET (tab), is_sensitive);
479 _refresh_notebook (AtkObject *aobject)
481 if (ATK_IS_OBJECT (aobject))
483 _greyout_tab (nbook_tabs[ACTION]->page, ATK_IS_ACTION(aobject));
484 _greyout_tab (nbook_tabs[COMPONENT]->page, ATK_IS_COMPONENT(aobject));
485 _greyout_tab (nbook_tabs[IMAGE]->page, ATK_IS_IMAGE(aobject));
486 _greyout_tab (nbook_tabs[SELECTION]->page, ATK_IS_SELECTION(aobject));
487 _greyout_tab (nbook_tabs[TABLE]->page, ATK_IS_TABLE(aobject));
488 _greyout_tab (nbook_tabs[TEXT]->page, ATK_IS_TEXT(aobject));
489 _greyout_tab (nbook_tabs[VALUE]->page, ATK_IS_VALUE(aobject));
493 static void _print_accessible (AtkObject *aobject)
497 if (_object_is_ours(aobject))
500 g_print("\nFocus entered the ferret output window!\n");
504 _refresh_notebook(aobject);
507 g_print("\nFocus change\n");
509 /* Do not attach signal handlers if the user has asked not to */
511 _update_handlers(aobject);
513 last_object = aobject; /* _update_handler normally does this */
515 top_tab = gtk_notebook_get_current_page (notebook) + OBJECT;
516 _update(top_tab, aobject);
523 if (ATK_IS_TEXT (aobject))
528 len = atk_text_get_character_count (ATK_TEXT (aobject));
529 atk_text_get_character_extents (ATK_TEXT (aobject), 0,
534 atk_text_get_character_extents (ATK_TEXT (aobject), len-1,
539 w = MAX (x0+w0, xN+wN) - x;
540 h = MAX (y0+h0, yN+hN) - y;
548 else if (ATK_IS_COMPONENT (aobject))
550 atk_component_get_extents (ATK_COMPONENT(aobject),
554 if (w > -1) _send_to_magnifier (x, y, w, h);
559 _object_is_ours (AtkObject *aobject)
561 /* determine whether this object is parented by our own accessible... */
563 AtkObject *toplevel = aobject;
565 while (atk_object_get_role(aobject) != ATK_ROLE_FRAME)
567 aobject = atk_object_get_parent (aobject);
568 if (aobject == NULL) break;
573 * Some widgets do not have an ATK_ROLE_FRAME at the top,
580 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (toplevel));
581 if (widget == mainWindow)
589 ferret_get_name_from_container (AtkObject *aobject)
592 gint n = atk_object_get_n_accessible_children (aobject);
595 while (!s && (i < n))
598 child = atk_object_ref_accessible_child (aobject, i);
599 if (ATK_IS_TEXT (child))
601 gint count = atk_text_get_character_count (ATK_TEXT (child));
602 s = atk_text_get_text (ATK_TEXT (child),
606 g_object_unref (child);
618 _print_object (AtkObject *aobject)
621 G_CONST_RETURN gchar * parent_name = NULL;
622 G_CONST_RETURN gchar * name = NULL;
623 G_CONST_RETURN gchar * description = NULL;
624 G_CONST_RETURN gchar * typename = NULL;
625 G_CONST_RETURN gchar * parent_typename = NULL;
626 G_CONST_RETURN gchar * role_name = NULL;
627 G_CONST_RETURN gchar * accel_name = NULL;
628 G_CONST_RETURN gchar * text = NULL;
630 AtkObject *parent = NULL;
631 static AtkObject *prev_aobject = NULL;
633 gint index_in_parent = -1;
636 TabNumber tab_n = OBJECT;
638 group_num = _print_groupname(tab_n, OBJECT_INTERFACE, "Object Interface");
640 name = atk_object_get_name (aobject);
641 typename = g_type_name (G_OBJECT_TYPE (aobject));
642 description = atk_object_get_description (aobject);
643 parent = atk_object_get_parent(aobject);
645 index_in_parent = atk_object_get_index_in_parent(aobject);
646 n_children = atk_object_get_n_accessible_children(aobject);
647 role = atk_object_get_role(aobject);
648 role_name = atk_role_get_name(role);
650 if (ATK_IS_ACTION (aobject))
652 accel_name = atk_action_get_keybinding (ATK_ACTION(aobject), 0);
653 if (!accel_name) accel_name = "";
660 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (aobject));
663 _print_key_value(tab_n, group_num, "Widget name",
664 (gpointer)gtk_widget_get_name (widget),
669 _print_key_value(tab_n, group_num, "Widget name", "No Widget",
675 _print_key_value(tab_n, group_num, "Accessible Type",
676 (gpointer)typename, VALUE_STRING);
680 _print_key_value(tab_n, group_num, "Accessible Type", "NULL",
686 _print_key_value(tab_n, group_num, "Accessible Name",
687 (gpointer)name, VALUE_STRING);
691 _print_key_value(tab_n, group_num, "Accessible Name", "(unknown)",
696 if (aobject != prev_aobject)
698 if (ATK_IS_TEXT (aobject) && !name)
701 atk_text_get_text_at_offset (ATK_TEXT (aobject),
703 ATK_TEXT_BOUNDARY_SENTENCE_END,
706 fprintf (stderr, "first sentence: %s\n", text);
707 _send_to_festival (role_name,
709 if (!name) name = "no name";
716 if (atk_object_get_role (aobject) == ATK_ROLE_TABLE_CELL)
718 gchar *cname = ferret_get_name_from_container (aobject);
719 if (cname) name = g_strdup (cname);
721 else if (atk_object_get_role (aobject) == ATK_ROLE_CHECK_BOX)
723 name = g_strdup ("check box");
730 _send_to_festival (role_name, name, accel_name);
737 parent_name = atk_object_get_name(parent);
739 parent_typename = g_type_name (G_OBJECT_TYPE (parent));
743 _print_key_value(tab_n, group_num, "Parent Accessible Type",
744 (gpointer)parent_typename, VALUE_STRING);
748 _print_key_value(tab_n, group_num,
749 "Parent Accessible Type", "NULL", VALUE_STRING);
754 _print_key_value(tab_n, group_num, "Parent Accessible Name",
755 (gpointer)parent_name, VALUE_STRING);
759 _print_key_value(tab_n, group_num,
760 "Parent Accessible Name", "NULL", VALUE_STRING);
763 output_str = g_strdup_printf("%d", index_in_parent);
764 _print_key_value(tab_n, group_num, "Index in Parent",
765 (gpointer)output_str, VALUE_STRING);
770 _print_key_value(tab_n, group_num, "Parent", "NULL", VALUE_STRING);
775 _print_key_value(tab_n, group_num, "Accessible Description",
776 (gpointer)description, VALUE_STRING);
780 _print_key_value(tab_n, group_num,
781 "Accessible Description", "NULL", VALUE_STRING);
786 _print_key_value(tab_n, group_num, "Accessible Role", (gpointer)role_name,
791 _print_key_value(tab_n, group_num, "Accessible Role", "NULL",
795 output_str = g_strdup_printf("%d", n_children);
796 _print_key_value(tab_n, group_num, "Number Children", (gpointer)output_str,
799 prev_aobject = aobject;
805 _print_relation (AtkObject *aobject)
807 AtkRelationSet* relation_set = atk_object_ref_relation_set (aobject);
808 gint n_relations = atk_relation_set_get_n_relations (relation_set);
810 TabNumber tab_n = OBJECT;
812 group_num = _print_groupname(tab_n, RELATION_INTERFACE,
813 "Relation Interface");
817 AtkRelation * relation;
818 G_CONST_RETURN gchar * relation_name = NULL;
819 G_CONST_RETURN gchar * relation_obj_name = NULL;
820 AtkRelationType relation_type;
821 AtkObject *relation_obj;
822 GPtrArray * relation_arry;
827 output_str = g_strdup_printf("%d", n_relations);
828 _print_key_value(tab_n, group_num,
829 "Number of Relations", (gpointer)output_str, VALUE_STRING);
832 for (i = 0; i < n_relations; i++)
834 relation = atk_relation_set_get_relation (relation_set, i);
836 relation_type = atk_relation_get_relation_type (relation);
837 relation_name = atk_relation_type_get_name (relation_type);
839 relation_arry = atk_relation_get_target(relation);
843 label_str = g_strdup_printf("Relation %d Name", i + 1);
844 _print_key_value(tab_n, group_num, label_str,
845 (gpointer)relation_name, VALUE_STRING);
850 label_str = g_strdup_printf("Relation %d Type", i + 1);
851 output_str = g_strdup_printf("%d", relation_type);
852 _print_key_value(tab_n, group_num, label_str,
853 (gpointer)output_str, VALUE_STRING);
858 label_str = g_strdup_printf("Relation %d with", i + 1);
859 output_str = g_strdup_printf("%d AtkObjects", relation_arry->len);
860 _print_key_value(tab_n, group_num, label_str, (gpointer)output_str,
865 for (j=0; j < relation_arry->len; j++)
867 label_str = g_strdup_printf(
868 "Relation %d,%d with AtkObject Name", i + 1, j + 1);
869 relation_obj = (AtkObject *)
870 g_ptr_array_index(relation_arry, j);
871 relation_obj_name = atk_object_get_name(relation_obj);
873 _print_key_value(tab_n, group_num, label_str,
874 (gpointer)relation_obj_name, VALUE_STRING);
879 g_object_unref (relation_set);
885 _print_state (AtkObject *aobject)
887 AtkStateSet *state_set = atk_object_ref_state_set(aobject);
889 TabNumber tab_n = OBJECT;
890 static AtkStateType states_to_track[] =
895 ATK_STATE_EXPANDABLE,
901 group_num = _print_groupname(tab_n, STATE_INTERFACE,
906 gboolean boolean_value;
907 AtkStateType one_state;
908 G_CONST_RETURN gchar *name;
911 for (i=0; i < sizeof(states_to_track)/sizeof(AtkStateType); i++)
913 one_state = (AtkStateType) states_to_track[i];
914 name = atk_state_type_get_name (one_state);
919 atk_state_set_contains_state (state_set, one_state);
920 _print_key_value(tab_n, group_num, name,
921 (gpointer)(&boolean_value), VALUE_BOOLEAN);
926 g_object_unref (state_set);
931 _print_action (AtkAction *aobject)
933 G_CONST_RETURN gchar *action_name;
934 G_CONST_RETURN gchar *action_description;
935 G_CONST_RETURN gchar *action_keybinding;
936 gchar *label_str, *output_str;
939 TabNumber tab_n = ACTION;
942 group_num = _print_groupname(tab_n, ACTION_INTERFACE,
945 num_actions = atk_action_get_n_actions (aobject);
946 output_str = g_strdup_printf("%d", num_actions);
947 _print_key_value(tab_n, group_num, "Number of Actions",
948 (gpointer) output_str, VALUE_STRING);
951 for (j = 0; j < num_actions; j++)
953 label_str = g_strdup_printf("Action %d Name", j + 1);
954 action_name = atk_action_get_name (aobject, j);
957 nv = _print_key_value(tab_n, group_num, label_str,
958 (gpointer) action_name, VALUE_BUTTON);
962 nv = _print_key_value(tab_n, group_num, label_str, "NULL",
966 nv->atkobj = ATK_OBJECT(aobject);
968 nv->signal_id = g_signal_connect (nv->button,
969 "clicked", G_CALLBACK (_action_cb), nv);
973 label_str = g_strdup_printf("Action %d Description", j + 1);
974 action_description = atk_action_get_description (aobject, j);
975 if (action_description)
977 _print_key_value(tab_n, group_num, label_str,
978 (gpointer)action_description, VALUE_STRING);
982 _print_key_value(tab_n, group_num, label_str, "NULL",
987 label_str = g_strdup_printf("Action %d Keybinding", j + 1);
988 action_keybinding = atk_action_get_keybinding (aobject, j);
989 if (action_keybinding)
991 _print_key_value(tab_n, group_num, label_str,
992 (gpointer)action_keybinding, VALUE_STRING);
996 _print_key_value(tab_n, group_num, label_str, "NULL",
1005 _print_component (AtkComponent *aobject)
1013 TabNumber tab_n = COMPONENT;
1015 group_num = _print_groupname(tab_n, COMPONENT_INTERFACE,
1016 "Component Interface");
1018 atk_component_get_extents (aobject,
1019 &x, &y, &width, &height, ATK_XY_SCREEN);
1021 output_str = g_strdup_printf("x: %d y: %d width: %d height %d",
1022 x, y, width, height);
1023 _print_key_value(tab_n, group_num, "Geometry", (gpointer)output_str,
1030 _print_image (AtkImage *aobject)
1032 G_CONST_RETURN gchar *image_desc;
1039 TabNumber tab_n = IMAGE;
1041 group_num = _print_groupname(tab_n, IMAGE_INTERFACE,
1044 image_desc = atk_image_get_image_description(aobject);
1047 _print_key_value(tab_n, group_num, "Description", (gpointer)image_desc,
1052 _print_key_value(tab_n, group_num, "Description", "NULL",
1056 atk_image_get_image_position(aobject, &x, &y, ATK_XY_SCREEN);
1057 atk_image_get_image_size(aobject, &height, &width);
1059 output_str = g_strdup_printf("x: %d y: %d width: %d height %d",
1060 x, y, width, height);
1061 _print_key_value(tab_n, group_num, "Geometry", (gpointer)output_str,
1068 _print_selection (AtkSelection *aobject)
1072 gchar *label_str, *output_str;
1074 gint n_selected, j, n_selectable;
1075 TabNumber tab_n = SELECTION;
1077 group_num = _print_groupname(tab_n, SELECTION_INTERFACE,
1078 "Selection Interface");
1080 n_selected = atk_selection_get_selection_count (aobject);
1081 output_str = g_strdup_printf ("%d", n_selected);
1082 _print_key_value (tab_n, group_num, "Number of Selected Children",
1083 (gpointer) output_str, VALUE_STRING);
1084 g_free (output_str);
1086 * The number of selected items is the number of children except for
1087 * a ComboBox where it is the number of items in the list.
1089 object = ATK_OBJECT (aobject);
1090 role = atk_object_get_role (object);
1091 if (role == ATK_ROLE_COMBO_BOX)
1093 object = atk_object_ref_accessible_child (object, 0);
1094 g_return_val_if_fail (atk_object_get_role (object) == ATK_ROLE_LIST,
1096 n_selectable = atk_object_get_n_accessible_children (object);
1097 g_object_unref (G_OBJECT (object));
1101 n_selectable = atk_object_get_n_accessible_children (object);
1103 output_str = g_strdup_printf ("%d", n_selectable);
1104 _print_key_value (tab_n, group_num, "Number of Selectable Children",
1105 (gpointer) output_str, VALUE_STRING);
1106 g_free (output_str);
1108 for (j = 0; j < n_selected; j++)
1110 G_CONST_RETURN gchar *selected_name;
1111 AtkObject *selected_object;
1113 selected_object = atk_selection_ref_selection (aobject, j);
1114 selected_name = atk_object_get_name (selected_object);
1115 if (selected_name == NULL)
1117 selected_name = "No name";
1119 label_str = g_strdup_printf ("Selected item: %d Name", j+1);
1120 _print_key_value (tab_n, group_num, label_str,
1121 (gpointer) selected_name, VALUE_STRING);
1123 g_object_unref (G_OBJECT (selected_object));
1129 _print_table (AtkTable *aobject)
1131 gchar *label_str, *output_str;
1132 G_CONST_RETURN gchar *col_desc;
1134 gint n_cols, n_rows;
1137 TabNumber tab_n = TABLE;
1139 group_num = _print_groupname(tab_n, TABLE_INTERFACE,
1142 n_cols = atk_table_get_n_columns(aobject);
1143 output_str = g_strdup_printf("%d", n_cols);
1144 _print_key_value(tab_n, group_num, "Number Columns", (gpointer)output_str,
1148 n_rows = atk_table_get_n_rows(aobject);
1149 output_str = g_strdup_printf("%d", n_rows);
1150 _print_key_value(tab_n, group_num, "Number Rows", (gpointer)output_str,
1154 caption = atk_table_get_caption(aobject);
1157 G_CONST_RETURN gchar* caption_name;
1159 caption_name = atk_object_get_name (caption);
1162 _print_key_value(tab_n, group_num, "Caption Name",
1163 (gpointer)caption_name, VALUE_STRING);
1167 for (i=0; i < n_cols; i++)
1169 label_str = g_strdup_printf("Column %d Description", i + 1);
1171 col_desc = atk_table_get_column_description(aobject, i);
1174 _print_key_value(tab_n, group_num, label_str, (gpointer)col_desc,
1179 _print_key_value(tab_n, group_num, label_str, "NULL",
1190 _print_text (AtkText *aobject)
1192 gchar *output_str, *text_val, *text_val_escaped;
1193 gint n_chars, caret_offset;
1194 gint start_offset, end_offset;
1197 TabNumber tab_n = TEXT;
1199 group_num = _print_groupname(tab_n, TEXT_INTERFACE,
1202 n_chars = atk_text_get_character_count(aobject);
1204 output_str = g_strdup_printf("%d", n_chars);
1205 _print_key_value(tab_n, group_num, "Total Character Count",
1206 (gpointer)output_str, VALUE_STRING);
1210 * Pass through g_strescape so that non-ASCII chars are made
1213 text_val = atk_text_get_text (aobject, 0, n_chars);
1216 text_val_escaped = g_strescape(text_val, NULL);
1217 _print_key_value (tab_n, group_num, "Text", (gpointer)text_val_escaped,
1220 g_free (text_val_escaped);
1224 _print_key_value (tab_n, group_num, "Text", "NULL", VALUE_TEXT);
1227 caret_offset = atk_text_get_caret_offset(aobject);
1228 output_str = g_strdup_printf("%d", caret_offset);
1229 _print_key_value(tab_n, group_num, "Caret Offset", (gpointer)output_str,
1233 if (caret_offset < 0)
1236 text_val = atk_text_get_text_at_offset (aobject, caret_offset,
1237 ATK_TEXT_BOUNDARY_CHAR,
1238 &start_offset, &end_offset);
1241 text_val_escaped = g_strescape(text_val, NULL);
1242 _print_key_value(tab_n, group_num, "Current Character",
1243 (gpointer)text_val_escaped, VALUE_STRING);
1245 g_free (text_val_escaped);
1249 _print_key_value(tab_n, group_num, "Current Character", "none",
1253 atk_text_get_character_extents (aobject, caret_offset,
1254 &x, &y, &w, &h, ATK_XY_SCREEN);
1255 output_str = g_strdup_printf ("(%d, %d) (%d, %d)", x, y, w, h);
1258 _print_key_value(tab_n, group_num, "Character Bounds (screen)",
1259 (gpointer)output_str, VALUE_STRING);
1263 atk_text_get_character_extents (aobject, caret_offset,
1264 &x, &y, &w, &h, ATK_XY_WINDOW);
1265 output_str = g_strdup_printf ("(%d, %d) (%d, %d)", x, y, w, h);
1268 _print_key_value(tab_n, group_num, "Character Bounds (window)",
1269 (gpointer)output_str, VALUE_STRING);
1273 text_val = atk_text_get_text_at_offset (aobject, caret_offset,
1274 ATK_TEXT_BOUNDARY_WORD_START,
1275 &start_offset, &end_offset);
1278 text_val_escaped = g_strescape(text_val, NULL);
1279 _print_key_value(tab_n, group_num, "Current Word",
1280 (gpointer)text_val_escaped, VALUE_STRING);
1282 g_free (text_val_escaped);
1286 _print_key_value(tab_n, group_num, "Current Word", "none",
1290 text_val = atk_text_get_text_at_offset (aobject, caret_offset,
1291 ATK_TEXT_BOUNDARY_LINE_START,
1292 &start_offset, &end_offset);
1295 text_val_escaped = g_strescape(text_val, NULL);
1296 _print_key_value(tab_n, group_num, "Current Line",
1297 (gpointer)text_val_escaped, VALUE_STRING);
1299 g_free (text_val_escaped);
1303 _print_key_value(tab_n, group_num, "Current Line", "none",
1307 text_val = atk_text_get_text_at_offset (aobject, caret_offset,
1308 ATK_TEXT_BOUNDARY_SENTENCE_START,
1309 &start_offset, &end_offset);
1312 text_val_escaped = g_strescape(text_val, NULL);
1313 _print_key_value(tab_n, group_num, "Current Sentence",
1314 (gpointer)text_val_escaped, VALUE_STRING);
1316 g_free (text_val_escaped);
1320 _print_key_value(tab_n, group_num, "Current Line", "none",
1327 _print_text_attributes (AtkText *aobject)
1329 AtkAttributeSet *attribute_set;
1330 AtkAttribute *attribute;
1331 gchar *output_str, *label_str;
1332 gint start_offset, end_offset, caret_offset;
1333 gint attribute_set_len, attribute_offset, i;
1335 TabNumber tab_n = TEXT;
1337 group_num = _print_groupname (tab_n, TEXT_ATTRIBUTES,
1338 "Text Attributes at Caret");
1340 caret_offset = atk_text_get_caret_offset(aobject);
1341 attribute_offset = caret_offset;
1346 attribute_set = atk_text_get_run_attributes(aobject, attribute_offset,
1347 &start_offset, &end_offset);
1349 label_str = g_strdup_printf("Attribute run start");
1351 output_str = g_strdup_printf("%d", start_offset);
1352 _print_key_value(tab_n, group_num, label_str, (gpointer)output_str,
1357 label_str = g_strdup_printf("Attribute run end");
1358 output_str = g_strdup_printf("%d", end_offset);
1359 _print_key_value(tab_n, group_num, label_str, (gpointer)output_str,
1364 if (attribute_set == NULL)
1365 attribute_set_len = 0;
1367 attribute_set_len = g_slist_length(attribute_set);
1369 label_str = g_strdup_printf("Number of Attributes");
1370 output_str = g_strdup_printf("%d", attribute_set_len);
1371 _print_key_value(tab_n, group_num, label_str, (gpointer)output_str,
1376 for (i=0; i < attribute_set_len; i++)
1378 attribute = ((AtkAttribute *) g_slist_nth(attribute_set, i)->data);
1380 _print_key_value(tab_n, group_num, attribute->name,
1381 (gpointer)attribute->value, VALUE_STRING);
1383 if (attribute_set != NULL)
1384 atk_attribute_set_free(attribute_set);
1391 _print_value (AtkValue *aobject)
1393 GValue *value_back, val;
1395 TabNumber tab_n = VALUE;
1399 group_num = _print_groupname(tab_n, VALUE_INTERFACE,
1402 atk_value_get_current_value(aobject, value_back);
1403 _print_value_type(group_num, "Value", value_back);
1404 atk_value_get_minimum_value(aobject, value_back);
1405 _print_value_type(group_num, "Minimum Value", value_back);
1406 atk_value_get_maximum_value(aobject, value_back);
1407 _print_value_type(group_num, "Maximum Value", value_back);
1412 _print_value_type(gint group_num, gchar *type, GValue *value)
1414 gchar *label_str = NULL;
1415 gchar *output_str = NULL;
1416 TabNumber tab_n = VALUE;
1418 if (G_VALUE_HOLDS_DOUBLE (value))
1420 label_str = g_strdup_printf("%s - Double", type);
1421 output_str = g_strdup_printf("%f",
1422 g_value_get_double (value));
1423 _print_key_value(tab_n, group_num, label_str, (gpointer)output_str,
1426 else if (G_VALUE_HOLDS_INT (value))
1428 label_str = g_strdup_printf("%s - Integer", type);
1429 output_str = g_strdup_printf("%d",
1430 g_value_get_int (value));
1431 _print_key_value(tab_n, group_num, label_str, (gpointer)output_str,
1436 _print_key_value(tab_n, group_num, "Value", "Unknown Type",
1447 _create_event_watcher (void)
1449 focus_tracker_id = atk_add_focus_tracker (_print_accessible);
1453 mouse_watcher_focus_id =
1454 atk_add_global_event_listener(_mouse_watcher,
1455 "Gtk:GtkWidget:enter_notify_event");
1456 mouse_watcher_button_id =
1457 atk_add_global_event_listener(_button_watcher,
1458 "Gtk:GtkWidget:button_press_event");
1463 _mouse_watcher (GSignalInvocationHint *ihint,
1464 guint n_param_values,
1465 const GValue *param_values,
1471 object = g_value_get_object (param_values + 0);
1473 if (GTK_IS_MENU(object)) return TRUE;
1475 g_assert (GTK_IS_WIDGET(object));
1477 widget = GTK_WIDGET (object);
1478 if (GTK_IS_WINDOW (widget))
1480 GtkWidget *focus_widget = gtk_window_get_focus (GTK_WINDOW (widget));
1481 if (focus_widget != NULL)
1482 widget = focus_widget;
1485 _print_accessible (gtk_widget_get_accessible (widget));
1490 _button_watcher (GSignalInvocationHint *ihint,
1491 guint n_param_values,
1492 const GValue *param_values,
1498 object = g_value_get_object (param_values + 0);
1500 widget = GTK_WIDGET (object);
1501 if (GTK_IS_CONTAINER (widget))
1503 if (G_VALUE_HOLDS_BOXED (param_values + 1))
1505 GdkEventButton *event;
1509 gint aobject_x, aobject_y;
1512 gp = g_value_get_boxed (param_values + 1);
1513 event = (GdkEventButton *) gp;
1514 aobject = gtk_widget_get_accessible (widget);
1515 aobject_x = aobject_y = 0;
1516 atk_component_get_position (ATK_COMPONENT (aobject),
1517 &aobject_x, &aobject_y,
1519 x = aobject_x + (gint) event->x;
1520 y = aobject_y + (gint) event->y;
1521 child = atk_component_ref_accessible_at_point (ATK_COMPONENT (aobject),
1527 _print_accessible (child);
1528 g_object_unref (child);
1532 if (!GTK_IS_MENU_ITEM (widget))
1534 g_print ("No child at position %d %d for %s\n",
1537 g_type_name (G_OBJECT_TYPE (widget)));
1546 static void _add_notebook_page (GtkNotebook *nbook,
1547 GtkWidget *content_widget,
1548 GtkWidget **new_page,
1549 const gchar *label_text)
1553 if (content_widget != NULL)
1555 *new_page = content_widget;
1559 *new_page = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
1562 label = gtk_label_new ("");
1563 gtk_label_set_markup_with_mnemonic (GTK_LABEL (label), label_text);
1564 gtk_notebook_append_page (notebook, *new_page, label);
1565 gtk_widget_show(*new_page);
1569 _create_notebook (void)
1572 notebook = GTK_NOTEBOOK (gtk_notebook_new());
1574 tab = nbook_tabs[OBJECT];
1575 _add_notebook_page (notebook, tab->main_box, &tab->page, "<b>_Object</b>");
1577 tab = nbook_tabs[ACTION];
1578 _add_notebook_page (notebook, tab->main_box, &tab->page, "<b>_Action</b>");
1580 tab = nbook_tabs[COMPONENT];
1581 _add_notebook_page (notebook, tab->main_box, &tab->page, "<b>_Component</b>");
1583 tab = nbook_tabs[IMAGE];
1584 _add_notebook_page (notebook, tab->main_box, &tab->page, "<b>_Image</b>");
1586 tab = nbook_tabs[SELECTION];
1587 _add_notebook_page (notebook, tab->main_box, &tab->page, "<b>_Selection</b>");
1589 tab = nbook_tabs[TABLE];
1590 _add_notebook_page (notebook, tab->main_box, &tab->page, "<b>_Table</b>");
1592 tab = nbook_tabs[TEXT];
1593 _add_notebook_page (notebook, tab->main_box, &tab->page, "<b>Te_xt</b>");
1595 tab = nbook_tabs[VALUE];
1596 _add_notebook_page (notebook, tab->main_box, &tab->page, "<b>_Value</b>");
1598 g_signal_connect (notebook,
1600 G_CALLBACK (_update_current_page),
1609 the_tab = g_new0(TabInfo, 1);
1610 the_tab->page = NULL;
1611 the_tab->main_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 20);
1612 the_tab->name = "Object";
1613 nbook_tabs[OBJECT] = the_tab;
1615 the_tab = g_new0(TabInfo, 1);
1616 the_tab->page = NULL;
1617 the_tab->main_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 20);
1618 the_tab->name = "Action";
1619 nbook_tabs[ACTION] = the_tab;
1621 the_tab = g_new0(TabInfo, 1);
1622 the_tab->page = NULL;
1623 the_tab->main_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 20);
1624 the_tab->name = "Component";
1625 nbook_tabs[COMPONENT] = the_tab;
1627 the_tab = g_new0(TabInfo, 1);
1628 the_tab->page = NULL;
1629 the_tab->main_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 20);
1630 the_tab->name = "Image";
1631 nbook_tabs[IMAGE] = the_tab;
1633 the_tab = g_new0(TabInfo, 1);
1634 the_tab->page = NULL;
1635 the_tab->main_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 20);
1636 the_tab->name = "Selection";
1637 nbook_tabs[SELECTION] = the_tab;
1639 the_tab = g_new0(TabInfo, 1);
1640 the_tab->page = NULL;
1641 the_tab->main_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 20);
1642 the_tab->name = "Table";
1643 nbook_tabs[TABLE] = the_tab;
1645 the_tab = g_new0(TabInfo, 1);
1646 the_tab->page = NULL;
1647 the_tab->main_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 20);
1648 the_tab->name = "Text";
1649 nbook_tabs[TEXT] = the_tab;
1651 the_tab = g_new0(TabInfo, 1);
1652 the_tab->page = NULL;
1653 the_tab->main_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 20);
1654 the_tab->name = "Value";
1655 nbook_tabs[VALUE] = the_tab;
1659 _create_window (void)
1661 static GtkWidget *window = NULL;
1665 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1666 gtk_widget_set_name (window, "Ferret Window");
1668 g_signal_connect (window, "destroy",
1669 G_CALLBACK (gtk_widget_destroyed),
1672 gtk_window_set_title (GTK_WINDOW (window), "GTK+ Ferret Output");
1673 gtk_window_set_default_size (GTK_WINDOW (window), 333, 550);
1674 gtk_container_set_border_width (GTK_CONTAINER (window), 0);
1676 vbox1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
1677 gtk_container_add (GTK_CONTAINER (window), vbox1);
1678 gtk_widget_show (vbox1);
1680 menubar = gtk_menu_bar_new ();
1681 gtk_box_pack_start (GTK_BOX (vbox1), menubar, FALSE, TRUE, 0);
1682 gtk_widget_show (menubar);
1683 menutop = gtk_menu_item_new_with_label("Menu");
1684 gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menutop);
1685 gtk_widget_show (menutop);
1686 menu = gtk_menu_new();
1687 gtk_menu_item_set_submenu (GTK_MENU_ITEM (menutop), menu);
1688 gtk_widget_show (menu);
1690 _add_menu(&menu, &menuitem_trackmouse, "Track Mouse", track_mouse,
1691 G_CALLBACK(_toggle_trackmouse));
1692 _add_menu(&menu, &menuitem_trackfocus, "Track Focus", track_focus,
1693 G_CALLBACK(_toggle_trackfocus));
1694 _add_menu(&menu, &menuitem_magnifier, "Magnifier", use_magnifier,
1695 G_CALLBACK(_toggle_magnifier));
1696 _add_menu(&menu, &menuitem_festival, "Festival", use_festival,
1697 G_CALLBACK(_toggle_festival));
1698 _add_menu(&menu, &menuitem_festival_terse, "Festival Terse",
1699 (!say_role && !say_accel),
1700 G_CALLBACK(_toggle_festival_terse));
1701 _add_menu(&menu, &menuitem_terminal, "Terminal Output", display_ascii,
1702 G_CALLBACK(_toggle_terminal));
1703 _add_menu(&menu, &menuitem_no_signals, "No ATK Signals", no_signals,
1704 G_CALLBACK(_toggle_no_signals));
1706 _create_notebook ();
1707 gtk_container_add (GTK_CONTAINER (vbox1), GTK_WIDGET (notebook));
1708 gtk_widget_show (GTK_WIDGET (notebook));
1710 if (!gtk_widget_get_visible (window))
1711 gtk_widget_show (window);
1713 mainWindow = GTK_WIDGET (window);
1717 _add_menu(GtkWidget ** menu, GtkWidget ** menuitem, gchar * name,
1718 gboolean init_value, GCallback func)
1720 *menuitem = gtk_check_menu_item_new_with_label(name);
1721 gtk_check_menu_item_set_active(
1722 GTK_CHECK_MENU_ITEM(*menuitem), init_value);
1723 gtk_menu_shell_append (GTK_MENU_SHELL (*menu), *menuitem);
1724 gtk_widget_show(*menuitem);
1725 g_signal_connect(*menuitem, "toggled", func, NULL);
1729 gtk_module_init(gint argc, char* argv[])
1731 if (g_getenv ("FERRET_ASCII"))
1732 display_ascii = TRUE;
1734 if (g_getenv ("FERRET_NOSIGNALS"))
1738 g_print("GTK ferret Module loaded\n");
1740 if (g_getenv("FERRET_MAGNIFIER"))
1741 use_magnifier = TRUE;
1743 if (g_getenv ("FERRET_FESTIVAL"))
1744 use_festival = TRUE;
1746 if (g_getenv ("FERRET_MOUSETRACK"))
1749 if (g_getenv ("FERRET_TERSE"))
1759 _create_event_watcher();
1765 _clear_tab(TabNumber tab_n)
1767 GList *group_list, *nv_list;
1772 tab = nbook_tabs[tab_n];
1774 for (group_list = tab->groups; group_list; group_list = group_list->next)
1776 group = (GroupInfo *) group_list->data;
1778 if (group->is_scrolled)
1779 gtk_widget_hide(GTK_WIDGET(group->scroll_outer_frame));
1781 gtk_widget_hide(GTK_WIDGET(group->frame));
1782 gtk_widget_hide(GTK_WIDGET(group->group_vbox));
1784 for (nv_list = group->name_value; nv_list; nv_list = nv_list->next)
1786 nv = (NameValue *) nv_list->data;
1788 gtk_widget_hide(GTK_WIDGET(nv->column1));
1789 gtk_widget_hide(GTK_WIDGET(nv->column2));
1790 gtk_widget_hide(GTK_WIDGET(nv->label));
1795 gtk_widget_hide(GTK_WIDGET(nv->string));
1798 gtk_widget_hide(GTK_WIDGET(nv->boolean));
1801 gtk_widget_hide(GTK_WIDGET(nv->text));
1804 gtk_widget_hide(GTK_WIDGET(nv->button));
1807 gtk_widget_hide(GTK_WIDGET(nv->hbox));
1809 /* Disconnect signal handler if any */
1810 if (nv->signal_id != -1)
1811 g_signal_handler_disconnect(nv->button, nv->signal_id);
1819 _print_groupname(TabNumber tab_n, GroupId group_id,
1820 const char *groupname)
1823 GroupInfo *the_group;
1827 g_print("\n<%s>\n", groupname);
1829 tab = nbook_tabs[tab_n];
1830 the_group = _get_group(tab, group_id, groupname);
1831 rc = g_list_index(tab->groups, the_group);
1836 _get_group(TabInfo *tab, GroupId group_id, const gchar *groupname)
1838 GroupInfo *group = NULL;
1839 gboolean found = FALSE;
1842 for (group_list = tab->groups; group_list; group_list = group_list->next)
1844 group = (GroupInfo *) group_list->data;
1845 if (group_id == group->group_id)
1854 /* build a new one */
1855 group = (GroupInfo *)g_new0(GroupInfo, 1);
1856 group->group_id = group_id;
1857 _get_group_scrolled(group);
1859 if (group->is_scrolled)
1861 group->frame = gtk_scrolled_window_new (NULL, NULL);
1862 gtk_widget_set_size_request (GTK_WIDGET (group->frame), -2,
1863 group->default_height);
1864 group->scroll_outer_frame = GTK_FRAME(gtk_frame_new(groupname));
1865 gtk_container_add(GTK_CONTAINER(group->scroll_outer_frame),
1870 group->frame = gtk_frame_new(groupname);
1873 gtk_container_set_border_width(GTK_CONTAINER(group->frame), 10);
1875 group->name = g_strdup(groupname);
1876 group->group_vbox = GTK_VBOX(gtk_box_new (GTK_ORIENTATION_VERTICAL, 10));
1878 if (group->is_scrolled)
1880 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (group->frame),
1881 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1882 gtk_scrolled_window_add_with_viewport(
1883 GTK_SCROLLED_WINDOW(group->frame),
1884 GTK_WIDGET(group->group_vbox));
1888 gtk_container_add(GTK_CONTAINER(group->frame),
1889 GTK_WIDGET(group->group_vbox));
1892 tab->groups = g_list_append (tab->groups, group);
1894 if (group->is_scrolled)
1896 gtk_box_pack_start (GTK_BOX (tab->main_box),
1897 GTK_WIDGET (group->scroll_outer_frame),
1902 gtk_box_pack_start (GTK_BOX (tab->main_box),
1903 GTK_WIDGET (group->frame),
1912 _get_group_scrolled(GroupInfo *group)
1914 if (group->group_id == OBJECT_INTERFACE)
1916 group->is_scrolled = FALSE;
1918 else if (group->group_id == RELATION_INTERFACE)
1920 group->is_scrolled = TRUE;
1921 group->default_height = 50;
1923 else if (group->group_id == STATE_INTERFACE)
1925 group->is_scrolled = TRUE;
1926 group->default_height = 100;
1928 else if (group->group_id == ACTION_INTERFACE)
1930 group->is_scrolled = TRUE;
1931 group->default_height = 200;
1933 else if (group->group_id == TEXT_ATTRIBUTES)
1935 group->is_scrolled = TRUE;
1936 group->default_height = 70;
1940 group->is_scrolled = FALSE;
1945 _get_name_value(GroupInfo *group, const gchar *label,
1946 gpointer value_ptr, ValueType type)
1948 NameValue *name_value = NULL;
1951 gboolean found = FALSE;
1952 static char *empty_string = "";
1956 label = empty_string;
1959 for (nv_list = group->name_value; nv_list; nv_list = nv_list->next)
1961 name_value = (NameValue *) nv_list->data;
1962 if (!name_value->active)
1971 name_value = (NameValue *)g_new0(NameValue, 1);
1972 name_value->column1 = GTK_HBOX(gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10));
1973 name_value->column2 = GTK_HBOX(gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10));
1974 name_value->hbox = GTK_HBOX(gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5));
1975 name_value->label = GTK_LABEL(gtk_label_new(label));
1976 name_value->string = gtk_label_new (NULL);
1977 name_value->boolean = gtk_check_button_new ();
1978 gtk_entry_buffer_set_max_length (gtk_entry_get_buffer (GTK_ENTRY (name_value->text)), 1000);
1979 name_value->button = GTK_BUTTON(gtk_button_new ());
1981 gtk_box_pack_end(GTK_BOX(name_value->column1),
1982 GTK_WIDGET(name_value->label), FALSE, FALSE, 10);
1987 gtk_label_set_text(GTK_LABEL(name_value->string),
1988 (gchar *) value_ptr);
1989 gtk_box_pack_start(GTK_BOX(name_value->column2),
1990 GTK_WIDGET(name_value->string), FALSE, FALSE, 10);
1993 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(name_value->boolean),
1994 *((gboolean *)value_ptr));
1995 gtk_widget_set_sensitive(name_value->boolean, FALSE);
1996 gtk_box_pack_start(GTK_BOX(name_value->column2),
1997 GTK_WIDGET(name_value->boolean), FALSE, FALSE, 10);
2000 gtk_entry_set_text (GTK_ENTRY (name_value->text),
2001 (gchar *)value_ptr);
2002 gtk_box_pack_start(GTK_BOX(name_value->column2),
2003 GTK_WIDGET(name_value->text), FALSE, FALSE, 10);
2005 value = &(name_value->button_gval);
2006 memset (value, 0, sizeof (GValue));
2007 g_value_init (value, G_TYPE_STRING);
2008 g_value_set_string (value, (gchar *)value_ptr);
2009 g_object_set_property(G_OBJECT(name_value->button),
2011 gtk_box_pack_start(GTK_BOX(name_value->column2),
2012 GTK_WIDGET(name_value->button), FALSE, FALSE, 10);
2016 gtk_box_pack_start (GTK_BOX (name_value->hbox),
2017 GTK_WIDGET (name_value->column1),
2019 gtk_box_pack_start (GTK_BOX (name_value->hbox),
2020 GTK_WIDGET (name_value->column2),
2022 gtk_container_add(GTK_CONTAINER(group->group_vbox),
2023 GTK_WIDGET(name_value->hbox));
2024 group->name_value = g_list_append (group->name_value, name_value);
2028 gtk_label_set_text(GTK_LABEL(name_value->label), label);
2032 gtk_label_set_text(GTK_LABEL(name_value->string),
2033 (gchar *) value_ptr);
2036 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(name_value->boolean),
2037 *((gboolean *)value_ptr));
2038 gtk_widget_set_sensitive(name_value->boolean, FALSE);
2041 gtk_entry_set_text (GTK_ENTRY (name_value->text),
2042 (gchar *) value_ptr);
2045 value = &(name_value->button_gval);
2046 memset (value, 0, sizeof (GValue));
2047 g_value_init (value, G_TYPE_STRING);
2048 g_value_set_string (value, (gchar *)value_ptr);
2049 g_object_set_property(G_OBJECT(name_value->button),
2055 name_value->active = TRUE;
2056 name_value->type = type;
2057 name_value->signal_id = -1;
2059 gtk_widget_show(GTK_WIDGET(name_value->label));
2064 gtk_widget_show(GTK_WIDGET(name_value->string));
2067 gtk_widget_show(GTK_WIDGET(name_value->boolean));
2070 gtk_widget_show(GTK_WIDGET(name_value->text));
2073 gtk_widget_show(GTK_WIDGET(name_value->button));
2077 gtk_widget_show(GTK_WIDGET(name_value->column1));
2078 gtk_widget_show(GTK_WIDGET(name_value->column2));
2079 gtk_widget_show(GTK_WIDGET(name_value->hbox));
2080 gtk_widget_show(GTK_WIDGET(group->group_vbox));
2086 _print_key_value(TabNumber tab_n, gint group_number,
2087 const char *label, gpointer value, ValueType type)
2090 GroupInfo *the_group;
2094 if (type == VALUE_BOOLEAN)
2096 if (*((gboolean *)value))
2097 g_print("\t%-30s\tTRUE\n", label);
2099 g_print("\t%-30s\tFALSE\n", label);
2103 g_print("\t%-30s\t%s\n", label,
2104 value ? (gchar *)value : "NULL");
2108 tab = nbook_tabs[tab_n];
2109 the_group = (GroupInfo *)g_list_nth_data(tab->groups, group_number);
2110 return _get_name_value(the_group, label, (gpointer)value, type);
2114 _finished_group(TabNumber tab_no, gint group_number)
2117 GroupInfo *the_group;
2119 tab = nbook_tabs[tab_no];
2121 the_group = (GroupInfo *)g_list_nth_data(tab->groups, group_number);
2123 if (the_group->is_scrolled)
2124 gtk_widget_show(GTK_WIDGET(the_group->scroll_outer_frame));
2126 gtk_widget_show(GTK_WIDGET(the_group->frame));
2127 gtk_widget_show(GTK_WIDGET(the_group->group_vbox));
2128 gtk_widget_show(GTK_WIDGET(tab->main_box));
2131 /* Signal handlers */
2133 static gulong child_added_id = 0;
2134 static gulong child_removed_id = 0;
2135 static gulong state_change_id = 0;
2137 static gulong text_caret_handler_id = 0;
2138 static gulong text_inserted_id = 0;
2139 static gulong text_deleted_id = 0;
2141 static gulong table_row_inserted_id = 0;
2142 static gulong table_column_inserted_id = 0;
2143 static gulong table_row_deleted_id = 0;
2144 static gulong table_column_deleted_id = 0;
2145 static gulong table_row_reordered_id = 0;
2146 static gulong table_column_reordered_id = 0;
2148 static gulong property_id = 0;
2151 _update_handlers(AtkObject *obj)
2153 /* Remove signal handlers from object that had focus before */
2155 if (last_object != NULL && G_TYPE_CHECK_INSTANCE(last_object))
2157 if (child_added_id != 0)
2158 g_signal_handler_disconnect(last_object, child_added_id);
2159 if (child_removed_id != 0)
2160 g_signal_handler_disconnect(last_object, child_removed_id);
2161 if (state_change_id != 0)
2162 g_signal_handler_disconnect(last_object, state_change_id);
2164 if (text_caret_handler_id != 0)
2165 g_signal_handler_disconnect(last_object, text_caret_handler_id);
2166 if (text_inserted_id != 0)
2167 g_signal_handler_disconnect(last_object, text_inserted_id);
2168 if (text_deleted_id != 0)
2169 g_signal_handler_disconnect(last_object, text_deleted_id);
2171 if (table_row_inserted_id != 0)
2172 g_signal_handler_disconnect(last_object, table_row_inserted_id);
2173 if (table_column_inserted_id != 0)
2174 g_signal_handler_disconnect(last_object, table_column_inserted_id);
2175 if (table_row_deleted_id != 0)
2176 g_signal_handler_disconnect(last_object, table_row_deleted_id);
2177 if (table_column_deleted_id != 0)
2178 g_signal_handler_disconnect(last_object, table_column_deleted_id);
2179 if (table_row_reordered_id != 0)
2180 g_signal_handler_disconnect(last_object, table_row_reordered_id);
2181 if (table_column_reordered_id != 0)
2182 g_signal_handler_disconnect(last_object, table_column_reordered_id);
2183 if (property_id != 0)
2184 g_signal_handler_disconnect(last_object, property_id);
2186 g_object_unref(last_object);
2192 child_removed_id = 0;
2193 text_caret_handler_id = 0;
2194 text_inserted_id = 0;
2195 text_deleted_id = 0;
2196 table_row_inserted_id = 0;
2197 table_column_inserted_id = 0;
2198 table_row_deleted_id = 0;
2199 table_column_deleted_id = 0;
2200 table_row_reordered_id = 0;
2201 table_column_reordered_id = 0;
2204 if (!G_TYPE_CHECK_INSTANCE(obj))
2210 /* Add signal handlers to object that now has focus. */
2212 if (ATK_IS_OBJECT(obj))
2214 child_added_id = g_signal_connect_closure (obj,
2215 "children_changed::add",
2216 g_cclosure_new (G_CALLBACK (_notify_object_child_added),
2217 NULL, NULL), FALSE);
2219 child_removed_id = g_signal_connect_closure (obj,
2220 "children_changed::remove",
2221 g_cclosure_new (G_CALLBACK (_notify_object_child_removed),
2222 NULL, NULL), FALSE);
2224 state_change_id = g_signal_connect_closure (obj,
2226 g_cclosure_new (G_CALLBACK (_notify_object_state_change),
2227 NULL, NULL), FALSE);
2230 if (ATK_IS_TEXT(obj))
2232 text_caret_handler_id = g_signal_connect_closure_by_id (obj,
2233 g_signal_lookup ("text_caret_moved", G_OBJECT_TYPE (obj)),
2234 0, g_cclosure_new (G_CALLBACK (_notify_caret_handler),
2235 NULL, NULL), FALSE);
2236 text_inserted_id = g_signal_connect_closure (obj,
2237 "text_changed::insert",
2238 g_cclosure_new (G_CALLBACK (_notify_text_insert_handler),
2239 NULL, NULL), FALSE);
2240 text_deleted_id = g_signal_connect_closure (obj,
2241 "text_changed::delete",
2242 g_cclosure_new (G_CALLBACK (_notify_text_delete_handler),
2243 NULL, NULL), FALSE);
2246 if (ATK_IS_TABLE(obj))
2248 table_row_inserted_id = g_signal_connect_closure_by_id (obj,
2249 g_signal_lookup ("row_inserted", G_OBJECT_TYPE (obj)),
2250 0, g_cclosure_new (G_CALLBACK (_notify_table_row_inserted),
2251 NULL, NULL), FALSE);
2252 table_column_inserted_id = g_signal_connect_closure_by_id (obj,
2253 g_signal_lookup ("column_inserted", G_OBJECT_TYPE (obj)),
2254 0, g_cclosure_new (G_CALLBACK (_notify_table_column_inserted),
2255 NULL, NULL), FALSE);
2256 table_row_deleted_id = g_signal_connect_closure_by_id (obj,
2257 g_signal_lookup ("row_deleted", G_OBJECT_TYPE (obj)),
2258 0, g_cclosure_new (G_CALLBACK (_notify_table_row_deleted),
2259 NULL, NULL), FALSE);
2260 table_column_deleted_id = g_signal_connect_closure_by_id (obj,
2261 g_signal_lookup ("column_deleted", G_OBJECT_TYPE (obj)),
2262 0, g_cclosure_new (G_CALLBACK (_notify_table_column_deleted),
2263 NULL, NULL), FALSE);
2264 table_row_reordered_id = g_signal_connect_closure_by_id (obj,
2265 g_signal_lookup ("row_reordered", G_OBJECT_TYPE (obj)),
2266 0, g_cclosure_new (G_CALLBACK (_notify_table_row_reordered),
2267 NULL, NULL), FALSE);
2268 table_column_reordered_id = g_signal_connect_closure_by_id (obj,
2269 g_signal_lookup ("column_reordered", G_OBJECT_TYPE (obj)),
2270 0, g_cclosure_new (G_CALLBACK (_notify_table_column_reordered),
2271 NULL, NULL), FALSE);
2274 property_id = g_signal_connect_closure_by_id (obj,
2275 g_signal_lookup ("property_change", G_OBJECT_TYPE (obj)),
2276 0, g_cclosure_new (G_CALLBACK (_property_change_handler),
2284 _notify_text_insert_handler (GObject *obj, int position, int offset)
2286 gchar *text = atk_text_get_text (ATK_TEXT (obj), position, position + offset);
2287 gchar *output_str = g_strdup_printf("position %d, length %d text: %s",
2288 position, offset, text ? text: "<NULL>");
2289 _print_signal(ATK_OBJECT(obj), FERRET_SIGNAL_TEXT,
2290 "Text Insert", output_str);
2295 _notify_text_delete_handler (GObject *obj, int position, int offset)
2297 gchar *text = atk_text_get_text (ATK_TEXT (obj), position, position + offset);
2298 gchar *output_str = g_strdup_printf("position %d, length %d text: %s",
2299 position, offset, text ? text: "<NULL>");
2300 _print_signal(ATK_OBJECT(obj), FERRET_SIGNAL_TEXT,
2301 "Text Delete", output_str);
2306 _notify_caret_handler (GObject *obj, int position)
2308 gchar *output_str = g_strdup_printf("position %d", position);
2309 _print_signal(ATK_OBJECT(obj), FERRET_SIGNAL_TEXT,
2310 "Text Caret Moved", output_str);
2317 _notify_table_row_inserted (GObject *obj, gint start_offset,
2321 g_strdup_printf("position %d, num of rows inserted %d!\n",
2322 start_offset, length);
2323 _print_signal(ATK_OBJECT(obj), FERRET_SIGNAL_TABLE,
2324 "Table Row Inserted", output_str);
2329 _notify_table_column_inserted (GObject *obj, gint start_offset,
2333 g_strdup_printf("position %d, num of rows inserted %d!\n",
2334 start_offset, length);
2335 _print_signal(ATK_OBJECT(obj), FERRET_SIGNAL_TABLE,
2336 "Table Column Inserted", output_str);
2341 _notify_table_row_deleted (GObject *obj, gint start_offset,
2344 gchar *output_str = g_strdup_printf("position %d, num of rows inserted %d!\n",
2345 start_offset, length);
2346 _print_signal(ATK_OBJECT(obj), FERRET_SIGNAL_TABLE,
2347 "Table Row Deleted", output_str);
2352 _notify_table_column_deleted (GObject *obj, gint start_offset,
2355 gchar *output_str = g_strdup_printf("position %d, num of rows inserted %d!\n",
2356 start_offset, length);
2357 _print_signal(ATK_OBJECT(obj), FERRET_SIGNAL_TABLE,
2358 "Table Column Deleted", output_str);
2363 _notify_table_row_reordered (GObject *obj)
2365 _print_signal(ATK_OBJECT(obj), FERRET_SIGNAL_TABLE,
2366 "Table Row Reordered", NULL);
2370 _notify_table_column_reordered (GObject *obj)
2372 _print_signal(ATK_OBJECT(obj), FERRET_SIGNAL_TABLE,
2373 "Table Column Reordered", NULL);
2376 /* Object signals */
2379 _notify_object_child_added (GObject *obj, gint index,
2382 gchar *output_str = g_strdup_printf("index %d", index);
2383 _print_signal(ATK_OBJECT(obj), FERRET_SIGNAL_OBJECT,
2384 "Child Added", output_str);
2389 _notify_object_child_removed (GObject *obj, gint index,
2392 gchar *output_str = g_strdup_printf("index %d", index);
2393 _print_signal(ATK_OBJECT(obj), FERRET_SIGNAL_OBJECT,
2394 "Child Removed", output_str);
2399 _notify_object_state_change (GObject *obj, gchar *name, gboolean set)
2401 gchar *output_str = g_strdup_printf("name %s %s set",
2402 name, set ? "is" : "was");
2403 _print_signal(ATK_OBJECT(obj), FERRET_SIGNAL_OBJECT,
2404 "State Change", output_str);
2409 /* Function to print signals */
2412 _print_signal(AtkObject *aobject, FerretSignalType type,
2413 const char *name, const char *info)
2415 TabNumber top_tab = gtk_notebook_get_current_page (notebook) + OBJECT;
2423 g_print("SIGNAL:\t%-34s\t%s\n", name, info);
2425 g_print("SIGNAL:\t%-34s\n", name);
2430 if ((type == FERRET_SIGNAL_TEXT) && (!strncmp(name, "Text Caret", 10)))
2432 _speak_caret_event (aobject);
2434 else if (type == FERRET_SIGNAL_TEXT)
2436 last_caret_offset = atk_text_get_caret_offset (ATK_TEXT (aobject));
2440 if (use_magnifier && ATK_IS_TEXT (aobject) &&
2441 (type == FERRET_SIGNAL_TEXT) && (!strncmp(name, "Text Caret", 10)))
2444 gint caret_offset = atk_text_get_caret_offset (ATK_TEXT (aobject));
2445 atk_text_get_character_extents ( ATK_TEXT (aobject), caret_offset, &x, &y, &w, &h, ATK_XY_SCREEN);
2446 _send_to_magnifier (x, y, w, h);
2449 if ((type == FERRET_SIGNAL_TEXT && top_tab == TEXT) ||
2450 (type == FERRET_SIGNAL_TABLE && top_tab == TABLE) ||
2451 (type == FERRET_SIGNAL_OBJECT && top_tab == OBJECT))
2454 g_print("Updating tab\n");
2456 _update(top_tab, aobject);
2460 /* Update functions */
2463 _update (TabNumber top_tab, AtkObject *aobject)
2467 if (top_tab >= OBJECT && top_tab < END_TABS)
2469 _clear_tab(top_tab);
2472 if (top_tab == OBJECT && ATK_IS_OBJECT(aobject))
2474 group_num = _print_object(aobject);
2475 _finished_group(OBJECT, group_num);
2476 group_num = _print_relation(aobject);
2477 _finished_group(OBJECT, group_num);
2478 group_num = _print_state(aobject);
2479 _finished_group(OBJECT, group_num);
2481 if (top_tab == TEXT && ATK_IS_TEXT(aobject))
2483 group_num = _print_text(ATK_TEXT (aobject));
2484 _finished_group(TEXT, group_num);
2485 group_num = _print_text_attributes(ATK_TEXT (aobject));
2486 _finished_group(TEXT, group_num);
2488 if (top_tab == SELECTION && ATK_IS_SELECTION(aobject))
2490 group_num = _print_selection(ATK_SELECTION (aobject));
2491 _finished_group(SELECTION, group_num);
2493 if (top_tab == TABLE && ATK_IS_TABLE(aobject))
2495 group_num = _print_table(ATK_TABLE (aobject));
2496 _finished_group(TABLE, group_num);
2498 if (top_tab == ACTION && ATK_IS_ACTION(aobject))
2500 group_num = _print_action(ATK_ACTION (aobject));
2501 _finished_group(ACTION, group_num);
2503 if (top_tab == COMPONENT && ATK_IS_COMPONENT(aobject))
2505 group_num = _print_component(ATK_COMPONENT(aobject));
2506 _finished_group(COMPONENT, group_num);
2508 if (top_tab == IMAGE && ATK_IS_IMAGE(aobject))
2510 group_num = _print_image(ATK_IMAGE (aobject));
2511 _finished_group(IMAGE, group_num);
2513 if (top_tab == VALUE && ATK_IS_VALUE(aobject))
2515 group_num = _print_value(ATK_VALUE(aobject));
2516 _finished_group(VALUE, group_num);
2521 _update_current_page(GtkNotebook *notebook, gpointer p, guint current_page)
2523 _update(current_page+OBJECT, last_object);
2526 /* Property listeners */
2528 static void _property_change_handler (AtkObject *obj,
2529 AtkPropertyValues *values)
2531 TabNumber top_tab = gtk_notebook_get_current_page (notebook) + OBJECT;
2537 * Only process if the property change corrisponds to the current
2540 if (obj != last_object)
2544 g_print("\nProperty change event <%s> for object not in focus\n",
2545 values->property_name);
2553 g_print("\nProperty change event <%s> occurred.\n",
2554 values->property_name);
2558 * Update the top tab if a property changes.
2560 * We may be able to ignore some property changes if they do not
2561 * change anything in ferret.
2564 if (top_tab == OBJECT &&
2565 ((strcmp (values->property_name, "accessible-name") == 0) ||
2566 (strcmp (values->property_name, "accessible-description") == 0) ||
2567 (strcmp (values->property_name, "accessible-parent") == 0) ||
2568 (strcmp (values->property_name, "accessible-value") == 0) ||
2569 (strcmp (values->property_name, "accessible-role") == 0) ||
2570 (strcmp (values->property_name, "accessible-component-layout") == 0) ||
2571 (strcmp (values->property_name, "accessible-component-mdi-zorder") == 0) ||
2572 (strcmp (values->property_name, "accessible-table-caption") == 0) ||
2573 (strcmp (values->property_name,
2574 "accessible-table-column-description") == 0) ||
2575 (strcmp (values->property_name,
2576 "accessible-table-column-header") == 0) ||
2577 (strcmp (values->property_name,
2578 "accessible-table-row-description") == 0) ||
2579 (strcmp (values->property_name,
2580 "accessible-table-row-header") == 0) ||
2581 (strcmp (values->property_name, "accessible-table-summary") == 0)))
2584 g_print("Updating tab\n");
2586 _update(top_tab, last_object);
2588 else if (top_tab == VALUE &&
2589 (strcmp (values->property_name, "accessible-value") == 0))
2592 g_print("Updating tab\n");
2594 _update(top_tab, last_object);
2598 /* Action button callback function */
2600 void _action_cb(GtkWidget *widget, gpointer *userdata)
2602 NameValue *nv = (NameValue *)userdata;
2603 atk_action_do_action(ATK_ACTION(nv->atkobj), nv->action_num);
2606 /* Menu-bar callback functions */
2608 void _toggle_terminal(GtkCheckMenuItem *checkmenuitem,
2611 if (gtk_check_menu_item_get_active (checkmenuitem))
2612 display_ascii = TRUE;
2614 display_ascii = FALSE;
2617 void _toggle_no_signals(GtkCheckMenuItem *checkmenuitem,
2620 if (gtk_check_menu_item_get_active (checkmenuitem))
2626 void _toggle_magnifier(GtkCheckMenuItem *checkmenuitem,
2629 if (gtk_check_menu_item_get_active (checkmenuitem))
2630 use_magnifier = TRUE;
2632 use_magnifier = FALSE;
2635 void _toggle_festival(GtkCheckMenuItem *checkmenuitem,
2638 if (gtk_check_menu_item_get_active (checkmenuitem))
2639 use_festival = TRUE;
2641 use_festival = FALSE;
2644 void _toggle_festival_terse(GtkCheckMenuItem *checkmenuitem,
2647 if (gtk_check_menu_item_get_active (checkmenuitem))
2659 void _toggle_trackmouse(GtkCheckMenuItem *checkmenuitem,
2662 if (gtk_check_menu_item_get_active (checkmenuitem))
2664 mouse_watcher_focus_id =
2665 atk_add_global_event_listener(_mouse_watcher,
2666 "Gtk:GtkWidget:enter_notify_event");
2667 mouse_watcher_button_id =
2668 atk_add_global_event_listener(_button_watcher,
2669 "Gtk:GtkWidget:button_press_event");
2674 if (mouse_watcher_focus_id != -1)
2676 atk_remove_global_event_listener(mouse_watcher_focus_id);
2677 atk_remove_global_event_listener(mouse_watcher_button_id);
2678 track_mouse = FALSE;
2683 void _toggle_trackfocus(GtkCheckMenuItem *checkmenuitem,
2686 if (gtk_check_menu_item_get_active (checkmenuitem))
2689 focus_tracker_id = atk_add_focus_tracker (_print_accessible);
2693 g_print ("No longer tracking focus.\n");
2694 track_focus = FALSE;
2695 atk_remove_focus_tracker (focus_tracker_id);