1 /* GAIL - The GNOME Accessibility Implementation Library
2 * Copyright 2001, 2002, 2003 Sun Microsystems Inc.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
24 #include "gailwindow.h"
25 #include "gailtoplevel.h"
26 #include "gail-private-macros.h"
41 static void gail_window_class_init (GailWindowClass *klass);
43 static void gail_window_init (GailWindow *accessible);
45 static void gail_window_real_initialize (AtkObject *obj,
47 static void gail_window_finalize (GObject *object);
49 static G_CONST_RETURN gchar* gail_window_get_name (AtkObject *accessible);
51 static AtkObject* gail_window_get_parent (AtkObject *accessible);
52 static gint gail_window_get_index_in_parent (AtkObject *accessible);
53 static gboolean gail_window_real_focus_gtk (GtkWidget *widget,
54 GdkEventFocus *event);
56 static AtkStateSet* gail_window_ref_state_set (AtkObject *accessible);
57 static AtkRelationSet* gail_window_ref_relation_set (AtkObject *accessible);
58 static void gail_window_real_notify_gtk (GObject *obj,
60 static gint gail_window_get_mdi_zorder (AtkComponent *component);
62 static gboolean gail_window_state_event_gtk (GtkWidget *widget,
63 GdkEventWindowState *event);
66 static void atk_component_interface_init (AtkComponentIface *iface);
68 static void gail_window_get_extents (AtkComponent *component,
73 AtkCoordType coord_type);
74 static void gail_window_get_size (AtkComponent *component,
78 static guint gail_window_signals [LAST_SIGNAL] = { 0, };
80 G_DEFINE_TYPE_WITH_CODE (GailWindow, gail_window, GAIL_TYPE_CONTAINER,
81 G_IMPLEMENT_INTERFACE (ATK_TYPE_COMPONENT, atk_component_interface_init))
84 gail_window_class_init (GailWindowClass *klass)
86 GailWidgetClass *widget_class;
87 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
88 AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
90 gobject_class->finalize = gail_window_finalize;
92 widget_class = (GailWidgetClass*)klass;
93 widget_class->focus_gtk = gail_window_real_focus_gtk;
94 widget_class->notify_gtk = gail_window_real_notify_gtk;
96 class->get_name = gail_window_get_name;
97 class->get_parent = gail_window_get_parent;
98 class->get_index_in_parent = gail_window_get_index_in_parent;
99 class->ref_relation_set = gail_window_ref_relation_set;
100 class->ref_state_set = gail_window_ref_state_set;
101 class->initialize = gail_window_real_initialize;
103 gail_window_signals [ACTIVATE] =
104 g_signal_new ("activate",
105 G_TYPE_FROM_CLASS (klass),
107 0, /* default signal handler */
109 g_cclosure_marshal_VOID__VOID,
111 gail_window_signals [CREATE] =
112 g_signal_new ("create",
113 G_TYPE_FROM_CLASS (klass),
115 0, /* default signal handler */
117 g_cclosure_marshal_VOID__VOID,
119 gail_window_signals [DEACTIVATE] =
120 g_signal_new ("deactivate",
121 G_TYPE_FROM_CLASS (klass),
123 0, /* default signal handler */
125 g_cclosure_marshal_VOID__VOID,
127 gail_window_signals [DESTROY] =
128 g_signal_new ("destroy",
129 G_TYPE_FROM_CLASS (klass),
131 0, /* default signal handler */
133 g_cclosure_marshal_VOID__VOID,
135 gail_window_signals [MAXIMIZE] =
136 g_signal_new ("maximize",
137 G_TYPE_FROM_CLASS (klass),
139 0, /* default signal handler */
141 g_cclosure_marshal_VOID__VOID,
143 gail_window_signals [MINIMIZE] =
144 g_signal_new ("minimize",
145 G_TYPE_FROM_CLASS (klass),
147 0, /* default signal handler */
149 g_cclosure_marshal_VOID__VOID,
151 gail_window_signals [MOVE] =
152 g_signal_new ("move",
153 G_TYPE_FROM_CLASS (klass),
155 0, /* default signal handler */
157 g_cclosure_marshal_VOID__VOID,
159 gail_window_signals [RESIZE] =
160 g_signal_new ("resize",
161 G_TYPE_FROM_CLASS (klass),
163 0, /* default signal handler */
165 g_cclosure_marshal_VOID__VOID,
167 gail_window_signals [RESTORE] =
168 g_signal_new ("restore",
169 G_TYPE_FROM_CLASS (klass),
171 0, /* default signal handler */
173 g_cclosure_marshal_VOID__VOID,
178 gail_window_init (GailWindow *accessible)
183 gail_window_real_initialize (AtkObject *obj,
186 GtkWidget *widget = GTK_WIDGET (data);
190 * A GailWindow can be created for a GtkHandleBox or a GtkWindow
192 if (!GTK_IS_WINDOW (widget) &&
193 !GTK_IS_HANDLE_BOX (widget))
194 gail_return_if_fail (FALSE);
196 ATK_OBJECT_CLASS (gail_window_parent_class)->initialize (obj, data);
198 window = GAIL_WINDOW (obj);
199 window->name_change_handler = 0;
200 window->previous_name = g_strdup (gtk_window_get_title (GTK_WINDOW (data)));
202 g_signal_connect (data,
203 "window_state_event",
204 G_CALLBACK (gail_window_state_event_gtk),
206 g_object_set_data (G_OBJECT (obj), "atk-component-layer",
207 GINT_TO_POINTER (ATK_LAYER_WINDOW));
209 if (GTK_IS_FILE_SELECTION (widget))
210 obj->role = ATK_ROLE_FILE_CHOOSER;
211 else if (GTK_IS_COLOR_SELECTION_DIALOG (widget))
212 obj->role = ATK_ROLE_COLOR_CHOOSER;
213 else if (GTK_IS_FONT_SELECTION_DIALOG (widget))
214 obj->role = ATK_ROLE_FONT_CHOOSER;
215 else if (GTK_IS_MESSAGE_DIALOG (widget))
216 obj->role = ATK_ROLE_ALERT;
217 else if (GTK_IS_DIALOG (widget))
218 obj->role = ATK_ROLE_DIALOG;
223 name = gtk_widget_get_name (widget);
224 if (name && (!strcmp (name, "gtk-tooltip") ||
225 !strcmp (name, "gtk-tooltips")))
226 obj->role = ATK_ROLE_TOOL_TIP;
227 else if (GTK_IS_PLUG (widget))
228 obj->role = ATK_ROLE_PANEL;
229 else if (GTK_WINDOW (widget)->type == GTK_WINDOW_POPUP)
230 obj->role = ATK_ROLE_WINDOW;
232 obj->role = ATK_ROLE_FRAME;
236 * Notify that tooltip is showing
238 if (obj->role == ATK_ROLE_TOOL_TIP &&
239 GTK_WIDGET_MAPPED (widget))
240 atk_object_notify_state_change (obj, ATK_STATE_SHOWING, 1);
244 gail_window_finalize (GObject *object)
246 GailWindow* window = GAIL_WINDOW (object);
248 if (window->name_change_handler)
250 g_source_remove (window->name_change_handler);
251 window->name_change_handler = 0;
253 if (window->previous_name)
255 g_free (window->previous_name);
256 window->previous_name = NULL;
259 G_OBJECT_CLASS (gail_window_parent_class)->finalize (object);
262 static G_CONST_RETURN gchar*
263 gail_window_get_name (AtkObject *accessible)
265 G_CONST_RETURN gchar* name;
267 name = ATK_OBJECT_CLASS (gail_window_parent_class)->get_name (accessible);
271 * Get the window title if it exists
273 GtkWidget* widget = GTK_ACCESSIBLE (accessible)->widget;
281 gail_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
283 if (GTK_IS_WINDOW (widget))
285 GtkWindow *window = GTK_WINDOW (widget);
287 name = gtk_window_get_title (window);
289 accessible->role == ATK_ROLE_TOOL_TIP)
293 child = gtk_bin_get_child (GTK_BIN (window));
294 /* could be some kind of egg notification bubble thingy? */
296 /* Handle new GTK+ GNOME 2.20 tooltips */
297 if (GTK_IS_ALIGNMENT(child))
299 child = gtk_bin_get_child (GTK_BIN (child));
300 if (GTK_IS_BOX(child))
304 children = gtk_container_get_children (GTK_CONTAINER (child));
305 count = g_list_length (children);
308 child = (GtkWidget *) g_list_nth_data (children, 1);
310 g_list_free (children);
314 if (!GTK_IS_LABEL (child))
316 g_message ("ATK_ROLE_TOOLTIP object found, but doesn't look like a tooltip.");
319 name = gtk_label_get_text (GTK_LABEL (child));
327 gail_window_get_parent (AtkObject *accessible)
331 parent = ATK_OBJECT_CLASS (gail_window_parent_class)->get_parent (accessible);
337 gail_window_get_index_in_parent (AtkObject *accessible)
339 GtkWidget* widget = GTK_ACCESSIBLE (accessible)->widget;
340 AtkObject* atk_obj = atk_get_root ();
349 gail_return_val_if_fail (GTK_IS_WIDGET (widget), -1);
351 index = ATK_OBJECT_CLASS (gail_window_parent_class)->get_index_in_parent (accessible);
355 if (GTK_IS_WINDOW (widget))
357 GtkWindow *window = GTK_WINDOW (widget);
358 if (GAIL_IS_TOPLEVEL (atk_obj))
360 GailToplevel* toplevel = GAIL_TOPLEVEL (atk_obj);
361 index = g_list_index (toplevel->window_list, window);
365 int i, sibling_count = atk_object_get_n_accessible_children (atk_obj);
366 for (i = 0; i < sibling_count && index == -1; ++i)
368 AtkObject *child = atk_object_ref_accessible_child (atk_obj, i);
369 if (accessible == child) index = i;
370 g_object_unref (G_OBJECT (child));
378 gail_window_real_focus_gtk (GtkWidget *widget,
379 GdkEventFocus *event)
383 obj = gtk_widget_get_accessible (widget);
384 atk_object_notify_state_change (obj, ATK_STATE_ACTIVE, event->in);
389 static AtkRelationSet*
390 gail_window_ref_relation_set (AtkObject *obj)
393 AtkRelationSet *relation_set;
395 AtkRelation* relation;
396 GtkWidget *current_widget;
398 gail_return_val_if_fail (GAIL_IS_WIDGET (obj), NULL);
400 widget = GTK_ACCESSIBLE (obj)->widget;
407 relation_set = ATK_OBJECT_CLASS (gail_window_parent_class)->ref_relation_set (obj);
409 if (atk_object_get_role (obj) == ATK_ROLE_TOOL_TIP)
411 relation = atk_relation_set_get_relation_by_type (relation_set, ATK_RELATION_POPUP_FOR);
415 atk_relation_set_remove (relation_set, relation);
417 if (GTK_WIDGET_VISIBLE(widget) && gtk_tooltips_get_info_from_tip_window (GTK_WINDOW (widget), NULL, ¤t_widget))
419 array [0] = gtk_widget_get_accessible (current_widget);
421 relation = atk_relation_new (array, 1, ATK_RELATION_POPUP_FOR);
422 atk_relation_set_add (relation_set, relation);
423 g_object_unref (relation);
430 gail_window_ref_state_set (AtkObject *accessible)
432 AtkStateSet *state_set;
435 GdkWindowState state;
437 state_set = ATK_OBJECT_CLASS (gail_window_parent_class)->ref_state_set (accessible);
438 widget = GTK_ACCESSIBLE (accessible)->widget;
443 window = GTK_WINDOW (widget);
445 if (window->has_focus)
446 atk_state_set_add_state (state_set, ATK_STATE_ACTIVE);
450 state = gdk_window_get_state (widget->window);
451 if (state & GDK_WINDOW_STATE_ICONIFIED)
452 atk_state_set_add_state (state_set, ATK_STATE_ICONIFIED);
454 if (gtk_window_get_modal (window))
455 atk_state_set_add_state (state_set, ATK_STATE_MODAL);
457 if (gtk_window_get_resizable (window))
458 atk_state_set_add_state (state_set, ATK_STATE_RESIZABLE);
464 idle_notify_name_change (gpointer data)
469 window = GAIL_WINDOW (data);
470 window->name_change_handler = 0;
471 if (GTK_ACCESSIBLE (window)->widget == NULL)
474 obj = ATK_OBJECT (window);
475 if (obj->name == NULL)
478 * The title has changed so notify a change in accessible-name
480 g_object_notify (G_OBJECT (obj), "accessible-name");
482 g_signal_emit_by_name (obj, "visible_data_changed");
488 gail_window_real_notify_gtk (GObject *obj,
491 GtkWidget *widget = GTK_WIDGET (obj);
492 AtkObject* atk_obj = gtk_widget_get_accessible (widget);
493 GailWindow *window = GAIL_WINDOW (atk_obj);
495 gboolean name_changed = FALSE;
497 if (strcmp (pspec->name, "title") == 0)
499 name = gtk_window_get_title (GTK_WINDOW (widget));
502 if (window->previous_name == NULL ||
503 strcmp (name, window->previous_name) != 0)
506 else if (window->previous_name != NULL)
511 g_free (window->previous_name);
512 window->previous_name = g_strdup (name);
514 if (window->name_change_handler == 0)
515 window->name_change_handler = gdk_threads_add_idle (idle_notify_name_change, atk_obj);
519 GAIL_WIDGET_CLASS (gail_window_parent_class)->notify_gtk (obj, pspec);
523 gail_window_state_event_gtk (GtkWidget *widget,
524 GdkEventWindowState *event)
528 obj = gtk_widget_get_accessible (widget);
529 atk_object_notify_state_change (obj, ATK_STATE_ICONIFIED,
530 (event->new_window_state & GDK_WINDOW_STATE_ICONIFIED) != 0);
535 atk_component_interface_init (AtkComponentIface *iface)
537 iface->get_extents = gail_window_get_extents;
538 iface->get_size = gail_window_get_size;
539 iface->get_mdi_zorder = gail_window_get_mdi_zorder;
543 gail_window_get_extents (AtkComponent *component,
548 AtkCoordType coord_type)
550 GtkWidget *widget = GTK_ACCESSIBLE (component)->widget;
552 gint x_toplevel, y_toplevel;
560 gail_return_if_fail (GTK_IS_WINDOW (widget));
562 if (!GTK_WIDGET_TOPLEVEL (widget))
564 AtkComponentIface *parent_iface;
566 parent_iface = (AtkComponentIface *) g_type_interface_peek_parent (ATK_COMPONENT_GET_IFACE (component));
567 parent_iface->get_extents (component, x, y, width, height, coord_type);
571 gdk_window_get_frame_extents (widget->window, &rect);
574 *height = rect.height;
575 if (!GTK_WIDGET_DRAWABLE (widget))
583 if (coord_type == ATK_XY_WINDOW)
585 gdk_window_get_origin (widget->window, &x_toplevel, &y_toplevel);
592 gail_window_get_size (AtkComponent *component,
596 GtkWidget *widget = GTK_ACCESSIBLE (component)->widget;
605 gail_return_if_fail (GTK_IS_WINDOW (widget));
607 if (!GTK_WIDGET_TOPLEVEL (widget))
609 AtkComponentIface *parent_iface;
611 parent_iface = (AtkComponentIface *) g_type_interface_peek_parent (ATK_COMPONENT_GET_IFACE (component));
612 parent_iface->get_size (component, width, height);
615 gdk_window_get_frame_extents (widget->window, &rect);
618 *height = rect.height;
621 #if defined (GDK_WINDOWING_X11)
623 #include <X11/Xlib.h>
624 #include <X11/Xatom.h>
625 #include <gdk/x11/gdkx.h>
627 /* _NET_CLIENT_LIST_STACKING monitoring */
630 Window *stacked_windows;
631 int stacked_windows_len;
632 GdkWindow *root_window;
633 guint update_handler;
635 guint update_desktop_handler;
636 gboolean *desktop_changed;
638 guint screen_initialized : 1;
639 guint update_stacked_windows : 1;
642 static GailScreenInfo *gail_screens = NULL;
643 static int num_screens = 0;
644 static Atom _net_client_list_stacking = None;
645 static Atom _net_wm_desktop = None;
648 get_window_desktop (Window window)
659 if (_net_wm_desktop == None)
661 XInternAtom (gdk_display, "_NET_WM_DESKTOP", False);
663 gdk_error_trap_push ();
664 result = XGetWindowProperty (gdk_display, window, _net_wm_desktop,
667 &ret_type, &format, &nitems,
668 &bytes_after, &cardinals);
669 error = gdk_error_trap_pop();
670 /* nitems < 1 will occur if the property is not set */
671 if (error != Success || result != Success || nitems < 1)
674 desktop = *cardinals;
683 free_screen_info (GailScreenInfo *info)
685 if (info->stacked_windows)
686 XFree (info->stacked_windows);
688 g_free (info->desktop);
689 if (info->desktop_changed)
690 g_free (info->desktop_changed);
692 info->stacked_windows = NULL;
693 info->stacked_windows_len = 0;
694 info->desktop = NULL;
695 info->desktop_changed = NULL;
699 get_stacked_windows (GailScreenInfo *info)
711 gboolean *desktops_changed;
713 if (_net_client_list_stacking == None)
714 _net_client_list_stacking =
715 XInternAtom (gdk_display, "_NET_CLIENT_LIST_STACKING", False);
717 gdk_error_trap_push ();
719 result = XGetWindowProperty (gdk_display,
720 GDK_WINDOW_XWINDOW (info->root_window),
721 _net_client_list_stacking,
723 False, XA_WINDOW, &ret_type, &format, &nitems,
724 &bytes_after, &data);
725 error = gdk_error_trap_pop ();
726 /* nitems < 1 will occur if the property is not set */
727 if (error != Success || result != Success || nitems < 1)
729 free_screen_info (info);
733 if (ret_type != XA_WINDOW)
736 free_screen_info (info);
740 desktops = g_malloc0 (nitems * sizeof (int));
741 desktops_changed = g_malloc0 (nitems * sizeof (gboolean));
742 for (i = 0; i < nitems; i++)
744 gboolean window_found = FALSE;
746 for (j = 0; j < info->stacked_windows_len; j++)
748 if (info->stacked_windows [j] == data [i])
750 desktops [i] = info->desktop [j];
751 desktops_changed [i] = info->desktop_changed [j];
758 desktops [i] = get_window_desktop (data [i]);
759 desktops_changed [i] = FALSE;
762 free_screen_info (info);
763 info->stacked_windows = (Window*) data;
764 info->stacked_windows_len = nitems;
765 info->desktop = desktops;
766 info->desktop_changed = desktops_changed;
772 update_screen_info (gpointer data)
774 int screen_n = GPOINTER_TO_INT (data);
776 gail_screens [screen_n].update_handler = 0;
777 gail_screens [screen_n].update_stacked_windows = FALSE;
779 get_stacked_windows (&gail_screens [screen_n]);
785 update_desktop_info (gpointer data)
787 int screen_n = GPOINTER_TO_INT (data);
788 GailScreenInfo *info;
791 info = &gail_screens [screen_n];
792 info->update_desktop_handler = 0;
794 for (i = 0; i < info->stacked_windows_len; i++)
796 if (info->desktop_changed [i])
798 info->desktop [i] = get_window_desktop (info->stacked_windows [i]);
799 info->desktop_changed [i] = FALSE;
806 static GdkFilterReturn
807 filter_func (GdkXEvent *gdkxevent,
811 XEvent *xevent = gdkxevent;
813 if (xevent->type == PropertyNotify)
815 if (xevent->xproperty.atom == _net_client_list_stacking)
820 window = event->any.window;
824 screen_n = gdk_screen_get_number (
825 gdk_drawable_get_screen (GDK_DRAWABLE (window)));
827 gail_screens [screen_n].update_stacked_windows = TRUE;
828 if (!gail_screens [screen_n].update_handler)
830 gail_screens [screen_n].update_handler = gdk_threads_add_idle (update_screen_info,
831 GINT_TO_POINTER (screen_n));
835 else if (xevent->xproperty.atom == _net_wm_desktop)
839 GailScreenInfo *info;
841 for (i = 0; i < num_screens; i++)
843 info = &gail_screens [i];
844 for (j = 0; j < info->stacked_windows_len; j++)
846 if (xevent->xany.window == info->stacked_windows [j])
848 info->desktop_changed [j] = TRUE;
849 if (!info->update_desktop_handler)
851 info->update_desktop_handler = gdk_threads_add_idle (update_desktop_info,
852 GINT_TO_POINTER (i));
860 return GDK_FILTER_CONTINUE;
864 display_closed (GdkDisplay *display,
869 for (i = 0; i < num_screens; i++)
871 if (gail_screens [i].update_handler)
873 g_source_remove (gail_screens [i].update_handler);
874 gail_screens [i].update_handler = 0;
877 if (gail_screens [i].update_desktop_handler)
879 g_source_remove (gail_screens [i].update_desktop_handler);
880 gail_screens [i].update_desktop_handler = 0;
883 free_screen_info (&gail_screens [i]);
886 g_free (gail_screens);
892 init_gail_screens (void)
896 display = gdk_display_get_default ();
898 num_screens = gdk_display_get_n_screens (display);
900 gail_screens = g_new0 (GailScreenInfo, num_screens);
901 gdk_window_add_filter (NULL, filter_func, NULL);
903 g_signal_connect (display, "closed", G_CALLBACK (display_closed), NULL);
907 init_gail_screen (GdkScreen *screen,
910 XWindowAttributes attrs;
912 gail_screens [screen_n].root_window = gdk_screen_get_root_window (screen);
914 get_stacked_windows (&gail_screens [screen_n]);
916 XGetWindowAttributes (gdk_display,
917 GDK_WINDOW_XWINDOW (gail_screens [screen_n].root_window),
920 XSelectInput (gdk_display,
921 GDK_WINDOW_XWINDOW (gail_screens [screen_n].root_window),
922 attrs.your_event_mask | PropertyChangeMask);
924 gail_screens [screen_n].screen_initialized = TRUE;
927 static GailScreenInfo *
928 get_screen_info (GdkScreen *screen)
932 gail_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
934 screen_n = gdk_screen_get_number (screen);
936 if (gail_screens && gail_screens [screen_n].screen_initialized)
937 return &gail_screens [screen_n];
940 init_gail_screens ();
942 g_assert (gail_screens != NULL);
944 init_gail_screen (screen, screen_n);
946 g_assert (gail_screens [screen_n].screen_initialized);
948 return &gail_screens [screen_n];
952 get_window_zorder (GdkWindow *window)
954 GailScreenInfo *info;
960 gail_return_val_if_fail (GDK_IS_WINDOW (window), -1);
962 info = get_screen_info (
963 gdk_drawable_get_screen (GDK_DRAWABLE (window)));
965 gail_return_val_if_fail (info->stacked_windows != NULL, -1);
967 xid = GDK_WINDOW_XID (window);
970 for (i = 0; i < info->stacked_windows_len; i++)
972 if (info->stacked_windows [i] == xid)
974 w_desktop = info->desktop[i];
982 for (i = 0; i < info->stacked_windows_len; i++)
984 if (info->stacked_windows [i] == xid)
990 if (info->desktop[i] == w_desktop)
999 gail_window_get_mdi_zorder (AtkComponent *component)
1001 GtkWidget *widget = GTK_ACCESSIBLE (component)->widget;
1009 gail_return_val_if_fail (GTK_IS_WINDOW (widget), -1);
1011 return get_window_zorder (widget->window);
1014 #elif defined (GDK_WINDOWING_WIN32)
1017 gail_window_get_mdi_zorder (AtkComponent *component)
1019 GtkWidget *widget = GTK_ACCESSIBLE (component)->widget;
1027 gail_return_val_if_fail (GTK_IS_WINDOW (widget), -1);
1029 return 0; /* Punt, FIXME */
1035 gail_window_get_mdi_zorder (AtkComponent *component)
1037 GtkWidget *widget = GTK_ACCESSIBLE (component)->widget;
1045 gail_return_val_if_fail (GTK_IS_WINDOW (widget), -1);
1047 return 0; /* Punt, FIXME */