]> Pileus Git - ~andy/gtk/blob - gtk/gtkwindow.c
Use G_STRFUNC instead __FUNCTION__
[~andy/gtk] / gtk / gtkwindow.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
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.
8  *
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.
13  *
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.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #include "config.h"
28 #include <string.h>
29 #include <stdlib.h>
30 #include <errno.h>
31 #include <limits.h>
32 #include "gdk/gdk.h"
33 #include "gdk/gdkkeysyms.h"
34
35 #include "gtkintl.h"
36
37 #include "gtkprivate.h"
38 #include "gtkrc.h"
39 #include "gtkwindow.h"
40 #include "gtkwindow-decorate.h"
41 #include "gtkbindings.h"
42 #include "gtkkeyhash.h"
43 #include "gtkmain.h"
44 #include "gtkmnemonichash.h"
45 #include "gtkiconfactory.h"
46 #include "gtkicontheme.h"
47 #include "gtkmarshalers.h"
48 #include "gtkplug.h"
49 #include "gtkbuildable.h"
50 #include "gtkalias.h"
51
52 #ifdef GDK_WINDOWING_X11
53 #include "x11/gdkx.h"
54 #endif
55
56 enum {
57   SET_FOCUS,
58   FRAME_EVENT,
59   ACTIVATE_FOCUS,
60   ACTIVATE_DEFAULT,
61   KEYS_CHANGED,
62   LAST_SIGNAL
63 };
64
65 enum {
66   PROP_0,
67
68   /* Construct */
69   PROP_TYPE,
70
71   /* Normal Props */
72   PROP_TITLE,
73   PROP_ROLE,
74   PROP_ALLOW_SHRINK,
75   PROP_ALLOW_GROW,
76   PROP_RESIZABLE,
77   PROP_MODAL,
78   PROP_WIN_POS,
79   PROP_DEFAULT_WIDTH,
80   PROP_DEFAULT_HEIGHT,
81   PROP_DESTROY_WITH_PARENT,
82   PROP_ICON,
83   PROP_ICON_NAME,
84   PROP_SCREEN,
85   PROP_TYPE_HINT,
86   PROP_SKIP_TASKBAR_HINT,
87   PROP_SKIP_PAGER_HINT,
88   PROP_URGENCY_HINT,
89   PROP_ACCEPT_FOCUS,
90   PROP_FOCUS_ON_MAP,
91   PROP_DECORATED,
92   PROP_DELETABLE,
93   PROP_GRAVITY,
94   PROP_TRANSIENT_FOR,
95   PROP_OPACITY,
96   
97   /* Readonly properties */
98   PROP_IS_ACTIVE,
99   PROP_HAS_TOPLEVEL_FOCUS,
100   
101   /* Writeonly properties */
102   PROP_STARTUP_ID,
103   
104   LAST_ARG
105 };
106
107 typedef struct
108 {
109   GList     *icon_list;
110   GdkPixmap *icon_pixmap;
111   GdkPixmap *icon_mask;
112   gchar     *icon_name;
113   guint      realized : 1;
114   guint      using_default_icon : 1;
115   guint      using_parent_icon : 1;
116   guint      using_themed_icon : 1;
117 } GtkWindowIconInfo;
118
119 typedef struct {
120   GdkGeometry    geometry; /* Last set of geometry hints we set */
121   GdkWindowHints flags;
122   GdkRectangle   configure_request;
123 } GtkWindowLastGeometryInfo;
124
125 struct _GtkWindowGeometryInfo
126 {
127   /* Properties that the app has set on the window
128    */
129   GdkGeometry    geometry;      /* Geometry hints */
130   GdkWindowHints mask;
131   GtkWidget     *widget;        /* subwidget to which hints apply */
132   /* from last gtk_window_resize () - if > 0, indicates that
133    * we should resize to this size.
134    */
135   gint           resize_width;  
136   gint           resize_height;
137
138   /* From last gtk_window_move () prior to mapping -
139    * only used if initial_pos_set
140    */
141   gint           initial_x;
142   gint           initial_y;
143   
144   /* Default size - used only the FIRST time we map a window,
145    * only if > 0.
146    */
147   gint           default_width; 
148   gint           default_height;
149   /* whether to use initial_x, initial_y */
150   guint          initial_pos_set : 1;
151   /* CENTER_ALWAYS or other position constraint changed since
152    * we sent the last configure request.
153    */
154   guint          position_constraints_changed : 1;
155
156   /* if true, default_width, height come from gtk_window_parse_geometry,
157    * and thus should be multiplied by the increments and affect the
158    * geometry widget only
159    */
160   guint          default_is_geometry : 1;
161   
162   GtkWindowLastGeometryInfo last;
163 };
164
165 #define GTK_WINDOW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_WINDOW, GtkWindowPrivate))
166
167 typedef struct _GtkWindowPrivate GtkWindowPrivate;
168
169 struct _GtkWindowPrivate
170 {
171   GtkMnemonicHash *mnemonic_hash;
172   
173   guint above_initially : 1;
174   guint below_initially : 1;
175   guint fullscreen_initially : 1;
176   guint skips_taskbar : 1;
177   guint skips_pager : 1;
178   guint urgent : 1;
179   guint accept_focus : 1;
180   guint focus_on_map : 1;
181   guint deletable : 1;
182   guint transient_parent_group : 1;
183
184   guint reset_type_hint : 1;
185   guint opacity_set : 1;
186   guint builder_visible : 1;
187
188   GdkWindowTypeHint type_hint;
189
190   gdouble opacity;
191
192   gchar *startup_id;
193 };
194
195 static void gtk_window_dispose            (GObject           *object);
196 static void gtk_window_destroy            (GtkObject         *object);
197 static void gtk_window_finalize           (GObject           *object);
198 static void gtk_window_show               (GtkWidget         *widget);
199 static void gtk_window_hide               (GtkWidget         *widget);
200 static void gtk_window_map                (GtkWidget         *widget);
201 static void gtk_window_unmap              (GtkWidget         *widget);
202 static void gtk_window_realize            (GtkWidget         *widget);
203 static void gtk_window_unrealize          (GtkWidget         *widget);
204 static void gtk_window_size_request       (GtkWidget         *widget,
205                                            GtkRequisition    *requisition);
206 static void gtk_window_size_allocate      (GtkWidget         *widget,
207                                            GtkAllocation     *allocation);
208 static gint gtk_window_event              (GtkWidget *widget,
209                                            GdkEvent *event);
210 static gboolean gtk_window_map_event      (GtkWidget         *widget,
211                                            GdkEventAny       *event);
212 static gboolean gtk_window_frame_event    (GtkWindow *window,
213                                            GdkEvent *event);
214 static gint gtk_window_configure_event    (GtkWidget         *widget,
215                                            GdkEventConfigure *event);
216 static gint gtk_window_key_press_event    (GtkWidget         *widget,
217                                            GdkEventKey       *event);
218 static gint gtk_window_key_release_event  (GtkWidget         *widget,
219                                            GdkEventKey       *event);
220 static gint gtk_window_enter_notify_event (GtkWidget         *widget,
221                                            GdkEventCrossing  *event);
222 static gint gtk_window_leave_notify_event (GtkWidget         *widget,
223                                            GdkEventCrossing  *event);
224 static gint gtk_window_focus_in_event     (GtkWidget         *widget,
225                                            GdkEventFocus     *event);
226 static gint gtk_window_focus_out_event    (GtkWidget         *widget,
227                                            GdkEventFocus     *event);
228 static gint gtk_window_client_event       (GtkWidget         *widget,
229                                            GdkEventClient    *event);
230 static void gtk_window_check_resize       (GtkContainer      *container);
231 static gint gtk_window_focus              (GtkWidget        *widget,
232                                            GtkDirectionType  direction);
233 static void gtk_window_real_set_focus     (GtkWindow         *window,
234                                            GtkWidget         *focus);
235
236 static void gtk_window_real_activate_default (GtkWindow         *window);
237 static void gtk_window_real_activate_focus   (GtkWindow         *window);
238 static void gtk_window_move_focus            (GtkWindow         *window,
239                                               GtkDirectionType   dir);
240 static void gtk_window_keys_changed          (GtkWindow         *window);
241 static void gtk_window_paint                 (GtkWidget         *widget,
242                                               GdkRectangle      *area);
243 static gint gtk_window_expose                (GtkWidget         *widget,
244                                               GdkEventExpose    *event);
245 static void gtk_window_unset_transient_for         (GtkWindow  *window);
246 static void gtk_window_transient_parent_realized   (GtkWidget  *parent,
247                                                     GtkWidget  *window);
248 static void gtk_window_transient_parent_unrealized (GtkWidget  *parent,
249                                                     GtkWidget  *window);
250
251 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
252
253 static GtkWindowGeometryInfo* gtk_window_get_geometry_info         (GtkWindow    *window,
254                                                                     gboolean      create);
255
256 static void     gtk_window_move_resize               (GtkWindow    *window);
257 static gboolean gtk_window_compare_hints             (GdkGeometry  *geometry_a,
258                                                       guint         flags_a,
259                                                       GdkGeometry  *geometry_b,
260                                                       guint         flags_b);
261 static void     gtk_window_constrain_size            (GtkWindow    *window,
262                                                       GdkGeometry  *geometry,
263                                                       guint         flags,
264                                                       gint          width,
265                                                       gint          height,
266                                                       gint         *new_width,
267                                                       gint         *new_height);
268 static void     gtk_window_constrain_position        (GtkWindow    *window,
269                                                       gint          new_width,
270                                                       gint          new_height,
271                                                       gint         *x,
272                                                       gint         *y);
273 static void     gtk_window_compute_hints             (GtkWindow    *window,
274                                                       GdkGeometry  *new_geometry,
275                                                       guint        *new_flags);
276 static void     gtk_window_compute_configure_request (GtkWindow    *window,
277                                                       GdkRectangle *request,
278                                                       GdkGeometry  *geometry,
279                                                       guint        *flags);
280
281 static void     gtk_window_set_default_size_internal (GtkWindow    *window,
282                                                       gboolean      change_width,
283                                                       gint          width,
284                                                       gboolean      change_height,
285                                                       gint          height,
286                                                       gboolean      is_geometry);
287
288 static void     update_themed_icon                    (GtkIconTheme *theme,
289                                                        GtkWindow    *window);
290 static GList   *icon_list_from_theme                  (GtkWidget    *widget,
291                                                        const gchar  *name);
292 static void     gtk_window_realize_icon               (GtkWindow    *window);
293 static void     gtk_window_unrealize_icon             (GtkWindow    *window);
294
295 static void        gtk_window_notify_keys_changed (GtkWindow   *window);
296 static GtkKeyHash *gtk_window_get_key_hash        (GtkWindow   *window);
297 static void        gtk_window_free_key_hash       (GtkWindow   *window);
298 static void        gtk_window_on_composited_changed (GdkScreen *screen,
299                                                      GtkWindow *window);
300
301 static GSList      *toplevel_list = NULL;
302 static guint        window_signals[LAST_SIGNAL] = { 0 };
303 static GList       *default_icon_list = NULL;
304 static gchar       *default_icon_name = NULL;
305 static guint        default_icon_serial = 0;
306 static gboolean     disable_startup_notification = FALSE;
307 static gboolean     sent_startup_notification = FALSE;
308
309 static GQuark       quark_gtk_embedded = 0;
310 static GQuark       quark_gtk_window_key_hash = 0;
311 static GQuark       quark_gtk_window_default_icon_pixmap = 0;
312 static GQuark       quark_gtk_window_icon_info = 0;
313 static GQuark       quark_gtk_buildable_accels = 0;
314
315 static GtkBuildableIface *parent_buildable_iface;
316
317 static void gtk_window_set_property (GObject         *object,
318                                      guint            prop_id,
319                                      const GValue    *value,
320                                      GParamSpec      *pspec);
321 static void gtk_window_get_property (GObject         *object,
322                                      guint            prop_id,
323                                      GValue          *value,
324                                      GParamSpec      *pspec);
325
326 /* GtkBuildable */
327 static void gtk_window_buildable_interface_init  (GtkBuildableIface *iface);
328 static void gtk_window_buildable_set_buildable_property (GtkBuildable        *buildable,
329                                                          GtkBuilder          *builder,
330                                                          const gchar         *name,
331                                                          const GValue        *value);
332 static void gtk_window_buildable_parser_finished (GtkBuildable     *buildable,
333                                                   GtkBuilder       *builder);
334 static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable  *buildable,
335                                                        GtkBuilder    *builder,
336                                                        GObject       *child,
337                                                        const gchar   *tagname,
338                                                        GMarkupParser *parser,
339                                                        gpointer      *data);
340 static void gtk_window_buildable_custom_finished (GtkBuildable  *buildable,
341                                                       GtkBuilder    *builder,
342                                                       GObject       *child,
343                                                       const gchar   *tagname,
344                                                       gpointer       user_data);
345
346
347 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
348                          G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
349                                                 gtk_window_buildable_interface_init))
350
351 static void
352 add_tab_bindings (GtkBindingSet    *binding_set,
353                   GdkModifierType   modifiers,
354                   GtkDirectionType  direction)
355 {
356   gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
357                                 "move-focus", 1,
358                                 GTK_TYPE_DIRECTION_TYPE, direction);
359   gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
360                                 "move-focus", 1,
361                                 GTK_TYPE_DIRECTION_TYPE, direction);
362 }
363
364 static void
365 add_arrow_bindings (GtkBindingSet    *binding_set,
366                     guint             keysym,
367                     GtkDirectionType  direction)
368 {
369   guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
370   
371   gtk_binding_entry_add_signal (binding_set, keysym, 0,
372                                 "move-focus", 1,
373                                 GTK_TYPE_DIRECTION_TYPE, direction);
374   gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
375                                 "move-focus", 1,
376                                 GTK_TYPE_DIRECTION_TYPE, direction);
377   gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
378                                 "move-focus", 1,
379                                 GTK_TYPE_DIRECTION_TYPE, direction);
380   gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
381                                 "move-focus", 1,
382                                 GTK_TYPE_DIRECTION_TYPE, direction);
383 }
384
385 static guint32
386 extract_time_from_startup_id (const gchar* startup_id)
387 {
388   gchar *timestr = g_strrstr (startup_id, "_TIME");
389   guint32 retval = GDK_CURRENT_TIME;
390
391   if (timestr)
392     {
393       gchar *end;
394       guint32 timestamp; 
395     
396       /* Skip past the "_TIME" part */
397       timestr += 5;
398
399       errno = 0;
400       timestamp = strtoul (timestr, &end, 0);
401       if (end != timestr && errno == 0)
402         retval = timestamp;
403     }
404
405   return retval;
406 }
407
408 static gboolean
409 startup_id_is_fake (const gchar* startup_id)
410 {
411   return strncmp (startup_id, "_TIME", 5) == 0;
412 }
413
414 static void
415 gtk_window_class_init (GtkWindowClass *klass)
416 {
417   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
418   GtkObjectClass *object_class;
419   GtkWidgetClass *widget_class;
420   GtkContainerClass *container_class;
421   GtkBindingSet *binding_set;
422   
423   object_class = (GtkObjectClass*) klass;
424   widget_class = (GtkWidgetClass*) klass;
425   container_class = (GtkContainerClass*) klass;
426   
427   quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded");
428   quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
429   quark_gtk_window_default_icon_pixmap = g_quark_from_static_string ("gtk-window-default-icon-pixmap");
430   quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
431   quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
432
433   gobject_class->dispose = gtk_window_dispose;
434   gobject_class->finalize = gtk_window_finalize;
435
436   gobject_class->set_property = gtk_window_set_property;
437   gobject_class->get_property = gtk_window_get_property;
438   
439   object_class->destroy = gtk_window_destroy;
440
441   widget_class->show = gtk_window_show;
442   widget_class->hide = gtk_window_hide;
443   widget_class->map = gtk_window_map;
444   widget_class->map_event = gtk_window_map_event;
445   widget_class->unmap = gtk_window_unmap;
446   widget_class->realize = gtk_window_realize;
447   widget_class->unrealize = gtk_window_unrealize;
448   widget_class->size_request = gtk_window_size_request;
449   widget_class->size_allocate = gtk_window_size_allocate;
450   widget_class->configure_event = gtk_window_configure_event;
451   widget_class->key_press_event = gtk_window_key_press_event;
452   widget_class->key_release_event = gtk_window_key_release_event;
453   widget_class->enter_notify_event = gtk_window_enter_notify_event;
454   widget_class->leave_notify_event = gtk_window_leave_notify_event;
455   widget_class->focus_in_event = gtk_window_focus_in_event;
456   widget_class->focus_out_event = gtk_window_focus_out_event;
457   widget_class->client_event = gtk_window_client_event;
458   widget_class->focus = gtk_window_focus;
459   
460   widget_class->expose_event = gtk_window_expose;
461    
462   container_class->check_resize = gtk_window_check_resize;
463
464   klass->set_focus = gtk_window_real_set_focus;
465   klass->frame_event = gtk_window_frame_event;
466
467   klass->activate_default = gtk_window_real_activate_default;
468   klass->activate_focus = gtk_window_real_activate_focus;
469   klass->move_focus = gtk_window_move_focus;
470   klass->keys_changed = gtk_window_keys_changed;
471   
472   g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
473   
474   /* Construct */
475   g_object_class_install_property (gobject_class,
476                                    PROP_TYPE,
477                                    g_param_spec_enum ("type",
478                                                       P_("Window Type"),
479                                                       P_("The type of the window"),
480                                                       GTK_TYPE_WINDOW_TYPE,
481                                                       GTK_WINDOW_TOPLEVEL,
482                                                       GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
483   /* Regular Props */
484   g_object_class_install_property (gobject_class,
485                                    PROP_TITLE,
486                                    g_param_spec_string ("title",
487                                                         P_("Window Title"),
488                                                         P_("The title of the window"),
489                                                         NULL,
490                                                         GTK_PARAM_READWRITE));
491
492   g_object_class_install_property (gobject_class,
493                                    PROP_ROLE,
494                                    g_param_spec_string ("role",
495                                                         P_("Window Role"),
496                                                         P_("Unique identifier for the window to be used when restoring a session"),
497                                                         NULL,
498                                                         GTK_PARAM_READWRITE));
499
500   /**
501    * GtkWindow:startup-id:
502    *
503    * The :startup-id is a write-only property for setting window's
504    * startup notification identifier. See gtk_window_set_startup_id()
505    * for more details.
506    *
507    * Since: 2.12
508    */
509   g_object_class_install_property (gobject_class,
510                                    PROP_STARTUP_ID,
511                                    g_param_spec_string ("startup-id",
512                                                         P_("Startup ID"),
513                                                         P_("Unique startup identifier for the window used by startup-notification"),
514                                                         NULL,
515                                                         GTK_PARAM_WRITABLE));
516
517   g_object_class_install_property (gobject_class,
518                                    PROP_ALLOW_SHRINK,
519                                    g_param_spec_boolean ("allow-shrink",
520                                                          P_("Allow Shrink"),
521                                                          /* xgettext:no-c-format */
522                                                          P_("If TRUE, the window has no mimimum size. Setting this to TRUE is 99% of the time a bad idea"),
523                                                          FALSE,
524                                                          GTK_PARAM_READWRITE));
525
526   g_object_class_install_property (gobject_class,
527                                    PROP_ALLOW_GROW,
528                                    g_param_spec_boolean ("allow-grow",
529                                                          P_("Allow Grow"),
530                                                          P_("If TRUE, users can expand the window beyond its minimum size"),
531                                                          TRUE,
532                                                          GTK_PARAM_READWRITE));
533
534   g_object_class_install_property (gobject_class,
535                                    PROP_RESIZABLE,
536                                    g_param_spec_boolean ("resizable",
537                                                          P_("Resizable"),
538                                                          P_("If TRUE, users can resize the window"),
539                                                          TRUE,
540                                                          GTK_PARAM_READWRITE));
541   
542   g_object_class_install_property (gobject_class,
543                                    PROP_MODAL,
544                                    g_param_spec_boolean ("modal",
545                                                          P_("Modal"),
546                                                          P_("If TRUE, the window is modal (other windows are not usable while this one is up)"),
547                                                          FALSE,
548                                                          GTK_PARAM_READWRITE));
549
550   g_object_class_install_property (gobject_class,
551                                    PROP_WIN_POS,
552                                    g_param_spec_enum ("window-position",
553                                                       P_("Window Position"),
554                                                       P_("The initial position of the window"),
555                                                       GTK_TYPE_WINDOW_POSITION,
556                                                       GTK_WIN_POS_NONE,
557                                                       GTK_PARAM_READWRITE));
558  
559   g_object_class_install_property (gobject_class,
560                                    PROP_DEFAULT_WIDTH,
561                                    g_param_spec_int ("default-width",
562                                                      P_("Default Width"),
563                                                      P_("The default width of the window, used when initially showing the window"),
564                                                      -1,
565                                                      G_MAXINT,
566                                                      -1,
567                                                      GTK_PARAM_READWRITE));
568   
569   g_object_class_install_property (gobject_class,
570                                    PROP_DEFAULT_HEIGHT,
571                                    g_param_spec_int ("default-height",
572                                                      P_("Default Height"),
573                                                      P_("The default height of the window, used when initially showing the window"),
574                                                      -1,
575                                                      G_MAXINT,
576                                                      -1,
577                                                      GTK_PARAM_READWRITE));
578   
579   g_object_class_install_property (gobject_class,
580                                    PROP_DESTROY_WITH_PARENT,
581                                    g_param_spec_boolean ("destroy-with-parent",
582                                                          P_("Destroy with Parent"),
583                                                          P_("If this window should be destroyed when the parent is destroyed"),
584                                                          FALSE,
585                                                          GTK_PARAM_READWRITE));
586
587   g_object_class_install_property (gobject_class,
588                                    PROP_ICON,
589                                    g_param_spec_object ("icon",
590                                                         P_("Icon"),
591                                                         P_("Icon for this window"),
592                                                         GDK_TYPE_PIXBUF,
593                                                         GTK_PARAM_READWRITE));
594   
595   /**
596    * GtkWindow:icon-name:
597    *
598    * The :icon-name property specifies the name of the themed icon to
599    * use as the window icon. See #GtkIconTheme for more details.
600    *
601    * Since: 2.6
602    */
603   g_object_class_install_property (gobject_class,
604                                    PROP_ICON_NAME,
605                                    g_param_spec_string ("icon-name",
606                                                         P_("Icon Name"),
607                                                         P_("Name of the themed icon for this window"),
608                                                         NULL,
609                                                         GTK_PARAM_READWRITE));
610   
611   g_object_class_install_property (gobject_class,
612                                    PROP_SCREEN,
613                                    g_param_spec_object ("screen",
614                                                         P_("Screen"),
615                                                         P_("The screen where this window will be displayed"),
616                                                         GDK_TYPE_SCREEN,
617                                                         GTK_PARAM_READWRITE));
618
619   g_object_class_install_property (gobject_class,
620                                    PROP_IS_ACTIVE,
621                                    g_param_spec_boolean ("is-active",
622                                                          P_("Is Active"),
623                                                          P_("Whether the toplevel is the current active window"),
624                                                          FALSE,
625                                                          GTK_PARAM_READABLE));
626   
627   g_object_class_install_property (gobject_class,
628                                    PROP_HAS_TOPLEVEL_FOCUS,
629                                    g_param_spec_boolean ("has-toplevel-focus",
630                                                          P_("Focus in Toplevel"),
631                                                          P_("Whether the input focus is within this GtkWindow"),
632                                                          FALSE,
633                                                          GTK_PARAM_READABLE));
634
635   g_object_class_install_property (gobject_class,
636                                    PROP_TYPE_HINT,
637                                    g_param_spec_enum ("type-hint",
638                                                       P_("Type hint"),
639                                                       P_("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
640                                                       GDK_TYPE_WINDOW_TYPE_HINT,
641                                                       GDK_WINDOW_TYPE_HINT_NORMAL,
642                                                       GTK_PARAM_READWRITE));
643
644   g_object_class_install_property (gobject_class,
645                                    PROP_SKIP_TASKBAR_HINT,
646                                    g_param_spec_boolean ("skip-taskbar-hint",
647                                                          P_("Skip taskbar"),
648                                                          P_("TRUE if the window should not be in the task bar."),
649                                                          FALSE,
650                                                          GTK_PARAM_READWRITE));
651
652   g_object_class_install_property (gobject_class,
653                                    PROP_SKIP_PAGER_HINT,
654                                    g_param_spec_boolean ("skip-pager-hint",
655                                                          P_("Skip pager"),
656                                                          P_("TRUE if the window should not be in the pager."),
657                                                          FALSE,
658                                                          GTK_PARAM_READWRITE));  
659
660   g_object_class_install_property (gobject_class,
661                                    PROP_URGENCY_HINT,
662                                    g_param_spec_boolean ("urgency-hint",
663                                                          P_("Urgent"),
664                                                          P_("TRUE if the window should be brought to the user's attention."),
665                                                          FALSE,
666                                                          GTK_PARAM_READWRITE));  
667
668   /**
669    * GtkWindow:accept-focus-hint:
670    *
671    * Whether the window should receive the input focus.
672    *
673    * Since: 2.4
674    */
675   g_object_class_install_property (gobject_class,
676                                    PROP_ACCEPT_FOCUS,
677                                    g_param_spec_boolean ("accept-focus",
678                                                          P_("Accept focus"),
679                                                          P_("TRUE if the window should receive the input focus."),
680                                                          TRUE,
681                                                          GTK_PARAM_READWRITE));  
682
683   /**
684    * GtkWindow:focus-on-map-hint:
685    *
686    * Whether the window should receive the input focus when mapped.
687    *
688    * Since: 2.6
689    */
690   g_object_class_install_property (gobject_class,
691                                    PROP_FOCUS_ON_MAP,
692                                    g_param_spec_boolean ("focus-on-map",
693                                                          P_("Focus on map"),
694                                                          P_("TRUE if the window should receive the input focus when mapped."),
695                                                          TRUE,
696                                                          GTK_PARAM_READWRITE));  
697
698   /**
699    * GtkWindow:decorated:
700    *
701    * Whether the window should be decorated by the window manager.
702    *
703    * Since: 2.4
704    */
705   g_object_class_install_property (gobject_class,
706                                    PROP_DECORATED,
707                                    g_param_spec_boolean ("decorated",
708                                                          P_("Decorated"),
709                                                          P_("Whether the window should be decorated by the window manager"),
710                                                          TRUE,
711                                                          GTK_PARAM_READWRITE));
712
713   /**
714    * GtkWindow:deletable:
715    *
716    * Whether the window frame should have a close button.
717    *
718    * Since: 2.10
719    */
720   g_object_class_install_property (gobject_class,
721                                    PROP_DELETABLE,
722                                    g_param_spec_boolean ("deletable",
723                                                          P_("Deletable"),
724                                                          P_("Whether the window frame should have a close button"),
725                                                          TRUE,
726                                                          GTK_PARAM_READWRITE));
727
728
729   /**
730    * GtkWindow:gravity:
731    *
732    * The window gravity of the window. See gtk_window_move() and #GdkGravity for
733    * more details about window gravity.
734    *
735    * Since: 2.4
736    */
737   g_object_class_install_property (gobject_class,
738                                    PROP_GRAVITY,
739                                    g_param_spec_enum ("gravity",
740                                                       P_("Gravity"),
741                                                       P_("The window gravity of the window"),
742                                                       GDK_TYPE_GRAVITY,
743                                                       GDK_GRAVITY_NORTH_WEST,
744                                                       GTK_PARAM_READWRITE));
745
746
747   /**
748    * GtkWindow:transient-for:
749    *
750    * The transient parent of the window. See gtk_window_set_transient_for() for
751    * more details about transient windows.
752    *
753    * Since: 2.10
754    */
755   g_object_class_install_property (gobject_class,
756                                    PROP_TRANSIENT_FOR,
757                                    g_param_spec_object ("transient-for",
758                                                         P_("Transient for Window"),
759                                                         P_("The transient parent of the dialog"),
760                                                         GTK_TYPE_WINDOW,
761                                                         GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
762
763   /**
764    * GtkWindow:opacity:
765    *
766    * The requested opacity of the window. See gtk_window_set_opacity() for
767    * more details about window opacity.
768    *
769    * Since: 2.12
770    */
771   g_object_class_install_property (gobject_class,
772                                    PROP_OPACITY,
773                                    g_param_spec_double ("opacity",
774                                                         P_("Opacity for Window"),
775                                                         P_("The opacity of the window, from 0 to 1"),
776                                                         0.0,
777                                                         1.0,
778                                                         1.0,
779                                                         GTK_PARAM_READWRITE));
780
781   window_signals[SET_FOCUS] =
782     g_signal_new (I_("set-focus"),
783                   G_TYPE_FROM_CLASS (gobject_class),
784                   G_SIGNAL_RUN_LAST,
785                   G_STRUCT_OFFSET (GtkWindowClass, set_focus),
786                   NULL, NULL,
787                   _gtk_marshal_VOID__OBJECT,
788                   G_TYPE_NONE, 1,
789                   GTK_TYPE_WIDGET);
790   
791   window_signals[FRAME_EVENT] =
792     g_signal_new (I_("frame-event"),
793                   G_TYPE_FROM_CLASS (gobject_class),
794                   G_SIGNAL_RUN_LAST,
795                   G_STRUCT_OFFSET(GtkWindowClass, frame_event),
796                   _gtk_boolean_handled_accumulator, NULL,
797                   _gtk_marshal_BOOLEAN__BOXED,
798                   G_TYPE_BOOLEAN, 1,
799                   GDK_TYPE_EVENT);
800
801   /**
802    * GtkWindow::activate-focus:
803    * @window: the window which received the signal
804    *
805    * The ::activate-default signal is a
806    * <link linkend="keybinding-signals">keybinding signal</link>
807    * which gets emitted when the user activates the currently
808    * focused widget of @window.
809    */
810   window_signals[ACTIVATE_FOCUS] =
811     g_signal_new (I_("activate-focus"),
812                   G_TYPE_FROM_CLASS (gobject_class),
813                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
814                   G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
815                   NULL, NULL,
816                   _gtk_marshal_VOID__VOID,
817                   G_TYPE_NONE,
818                   0);
819
820   /**
821    * GtkWindow::activate-default:
822    * @window: the window which received the signal
823    *
824    * The ::activate-default signal is a
825    * <link linkend="keybinding-signals">keybinding signal</link>
826    * which gets emitted when the user activates the default widget
827    * of @window.
828    */
829   window_signals[ACTIVATE_DEFAULT] =
830     g_signal_new (I_("activate-default"),
831                   G_TYPE_FROM_CLASS (gobject_class),
832                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
833                   G_STRUCT_OFFSET (GtkWindowClass, activate_default),
834                   NULL, NULL,
835                   _gtk_marshal_VOID__VOID,
836                   G_TYPE_NONE,
837                   0);
838
839   /**
840    * GtkWindow::keys-changed:
841    * @window: the window which received the signal
842    *
843    * The ::keys-changed signal gets emitted when the set of accelerators
844    * or mnemonics that are associated with @window changes.
845    */
846   window_signals[KEYS_CHANGED] =
847     g_signal_new (I_("keys-changed"),
848                   G_TYPE_FROM_CLASS (gobject_class),
849                   G_SIGNAL_RUN_FIRST,
850                   G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
851                   NULL, NULL,
852                   _gtk_marshal_VOID__VOID,
853                   G_TYPE_NONE,
854                   0);
855
856   /*
857    * Key bindings
858    */
859
860   binding_set = gtk_binding_set_by_class (klass);
861
862   gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
863                                 "activate-focus", 0);
864   gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0,
865                                 "activate-focus", 0);
866   
867   gtk_binding_entry_add_signal (binding_set, GDK_Return, 0,
868                                 "activate-default", 0);
869   gtk_binding_entry_add_signal (binding_set, GDK_ISO_Enter, 0,
870                                 "activate-default", 0);
871   gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
872                                 "activate-default", 0);
873
874   add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
875   add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
876   add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
877   add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
878
879   add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
880   add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
881   add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
882   add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
883 }
884
885 static void
886 gtk_window_init (GtkWindow *window)
887 {
888   GdkColormap *colormap;
889   GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
890   
891   GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
892   GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
893
894   GTK_PRIVATE_SET_FLAG (window, GTK_ANCHORED);
895
896   gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
897
898   window->title = NULL;
899   window->wmclass_name = g_strdup (g_get_prgname ());
900   window->wmclass_class = g_strdup (gdk_get_program_class ());
901   window->wm_role = NULL;
902   window->geometry_info = NULL;
903   window->type = GTK_WINDOW_TOPLEVEL;
904   window->focus_widget = NULL;
905   window->default_widget = NULL;
906   window->configure_request_count = 0;
907   window->allow_shrink = FALSE;
908   window->allow_grow = TRUE;
909   window->configure_notify_received = FALSE;
910   window->position = GTK_WIN_POS_NONE;
911   window->need_default_size = TRUE;
912   window->need_default_position = TRUE;
913   window->modal = FALSE;
914   window->frame = NULL;
915   window->has_frame = FALSE;
916   window->frame_left = 0;
917   window->frame_right = 0;
918   window->frame_top = 0;
919   window->frame_bottom = 0;
920   window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
921   window->gravity = GDK_GRAVITY_NORTH_WEST;
922   window->decorated = TRUE;
923   window->mnemonic_modifier = GDK_MOD1_MASK;
924   window->screen = gdk_screen_get_default ();
925
926   priv->accept_focus = TRUE;
927   priv->focus_on_map = TRUE;
928   priv->deletable = TRUE;
929   priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
930   priv->opacity = 1.0;
931   priv->startup_id = NULL;
932
933   colormap = _gtk_widget_peek_colormap ();
934   if (colormap)
935     gtk_widget_set_colormap (GTK_WIDGET (window), colormap);
936   
937   g_object_ref_sink (window);
938   window->has_user_ref_count = TRUE;
939   toplevel_list = g_slist_prepend (toplevel_list, window);
940
941   gtk_decorated_window_init (window);
942
943   g_signal_connect (window->screen, "composited-changed",
944                     G_CALLBACK (gtk_window_on_composited_changed), window);
945 }
946
947 static void
948 gtk_window_set_property (GObject      *object,
949                          guint         prop_id,
950                          const GValue *value,
951                          GParamSpec   *pspec)
952 {
953   GtkWindow  *window;
954   
955   window = GTK_WINDOW (object);
956
957   switch (prop_id)
958     {
959     case PROP_TYPE:
960       window->type = g_value_get_enum (value);
961       break;
962     case PROP_TITLE:
963       gtk_window_set_title (window, g_value_get_string (value));
964       break;
965     case PROP_ROLE:
966       gtk_window_set_role (window, g_value_get_string (value));
967       break;
968     case PROP_STARTUP_ID:
969       gtk_window_set_startup_id (window, g_value_get_string (value));
970       break; 
971     case PROP_ALLOW_SHRINK:
972       window->allow_shrink = g_value_get_boolean (value);
973       gtk_widget_queue_resize (GTK_WIDGET (window));
974       break;
975     case PROP_ALLOW_GROW:
976       window->allow_grow = g_value_get_boolean (value);
977       gtk_widget_queue_resize (GTK_WIDGET (window));
978       g_object_notify (G_OBJECT (window), "resizable");
979       break;
980     case PROP_RESIZABLE:
981       window->allow_grow = g_value_get_boolean (value);
982       gtk_widget_queue_resize (GTK_WIDGET (window));
983       g_object_notify (G_OBJECT (window), "allow-grow");
984       break;
985     case PROP_MODAL:
986       gtk_window_set_modal (window, g_value_get_boolean (value));
987       break;
988     case PROP_WIN_POS:
989       gtk_window_set_position (window, g_value_get_enum (value));
990       break;
991     case PROP_DEFAULT_WIDTH:
992       gtk_window_set_default_size_internal (window,
993                                             TRUE, g_value_get_int (value),
994                                             FALSE, -1, FALSE);
995       break;
996     case PROP_DEFAULT_HEIGHT:
997       gtk_window_set_default_size_internal (window,
998                                             FALSE, -1,
999                                             TRUE, g_value_get_int (value), FALSE);
1000       break;
1001     case PROP_DESTROY_WITH_PARENT:
1002       gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
1003       break;
1004     case PROP_ICON:
1005       gtk_window_set_icon (window,
1006                            g_value_get_object (value));
1007       break;
1008     case PROP_ICON_NAME:
1009       gtk_window_set_icon_name (window, g_value_get_string (value));
1010       break;
1011     case PROP_SCREEN:
1012       gtk_window_set_screen (window, g_value_get_object (value));
1013       break;
1014     case PROP_TYPE_HINT:
1015       gtk_window_set_type_hint (window,
1016                                 g_value_get_enum (value));
1017       break;
1018     case PROP_SKIP_TASKBAR_HINT:
1019       gtk_window_set_skip_taskbar_hint (window,
1020                                         g_value_get_boolean (value));
1021       break;
1022     case PROP_SKIP_PAGER_HINT:
1023       gtk_window_set_skip_pager_hint (window,
1024                                       g_value_get_boolean (value));
1025       break;
1026     case PROP_URGENCY_HINT:
1027       gtk_window_set_urgency_hint (window,
1028                                    g_value_get_boolean (value));
1029       break;
1030     case PROP_ACCEPT_FOCUS:
1031       gtk_window_set_accept_focus (window,
1032                                    g_value_get_boolean (value));
1033       break;
1034     case PROP_FOCUS_ON_MAP:
1035       gtk_window_set_focus_on_map (window,
1036                                    g_value_get_boolean (value));
1037       break;
1038     case PROP_DECORATED:
1039       gtk_window_set_decorated (window, g_value_get_boolean (value));
1040       break;
1041     case PROP_DELETABLE:
1042       gtk_window_set_deletable (window, g_value_get_boolean (value));
1043       break;
1044     case PROP_GRAVITY:
1045       gtk_window_set_gravity (window, g_value_get_enum (value));
1046       break;
1047     case PROP_TRANSIENT_FOR:
1048       gtk_window_set_transient_for (window, g_value_get_object (value));
1049       break;
1050     case PROP_OPACITY:
1051       gtk_window_set_opacity (window, g_value_get_double (value));
1052       break;
1053     default:
1054       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1055       break;
1056     }
1057 }
1058
1059 static void
1060 gtk_window_get_property (GObject      *object,
1061                          guint         prop_id,
1062                          GValue       *value,
1063                          GParamSpec   *pspec)
1064 {
1065   GtkWindow  *window;
1066   GtkWindowPrivate *priv;
1067
1068   window = GTK_WINDOW (object);
1069   priv = GTK_WINDOW_GET_PRIVATE (window);
1070   
1071   switch (prop_id)
1072     {
1073       GtkWindowGeometryInfo *info;
1074     case PROP_TYPE:
1075       g_value_set_enum (value, window->type);
1076       break;
1077     case PROP_ROLE:
1078       g_value_set_string (value, window->wm_role);
1079       break;
1080     case PROP_TITLE:
1081       g_value_set_string (value, window->title);
1082       break;
1083     case PROP_ALLOW_SHRINK:
1084       g_value_set_boolean (value, window->allow_shrink);
1085       break;
1086     case PROP_ALLOW_GROW:
1087       g_value_set_boolean (value, window->allow_grow);
1088       break;
1089     case PROP_RESIZABLE:
1090       g_value_set_boolean (value, window->allow_grow);
1091       break;
1092     case PROP_MODAL:
1093       g_value_set_boolean (value, window->modal);
1094       break;
1095     case PROP_WIN_POS:
1096       g_value_set_enum (value, window->position);
1097       break;
1098     case PROP_DEFAULT_WIDTH:
1099       info = gtk_window_get_geometry_info (window, FALSE);
1100       if (!info)
1101         g_value_set_int (value, -1);
1102       else
1103         g_value_set_int (value, info->default_width);
1104       break;
1105     case PROP_DEFAULT_HEIGHT:
1106       info = gtk_window_get_geometry_info (window, FALSE);
1107       if (!info)
1108         g_value_set_int (value, -1);
1109       else
1110         g_value_set_int (value, info->default_height);
1111       break;
1112     case PROP_DESTROY_WITH_PARENT:
1113       g_value_set_boolean (value, window->destroy_with_parent);
1114       break;
1115     case PROP_ICON:
1116       g_value_set_object (value, gtk_window_get_icon (window));
1117       break;
1118     case PROP_ICON_NAME:
1119       g_value_set_string (value, gtk_window_get_icon_name (window));
1120       break;
1121     case PROP_SCREEN:
1122       g_value_set_object (value, window->screen);
1123       break;
1124     case PROP_IS_ACTIVE:
1125       g_value_set_boolean (value, window->is_active);
1126       break;
1127     case PROP_HAS_TOPLEVEL_FOCUS:
1128       g_value_set_boolean (value, window->has_toplevel_focus);
1129       break;
1130     case PROP_TYPE_HINT:
1131       g_value_set_enum (value, priv->type_hint);
1132       break;
1133     case PROP_SKIP_TASKBAR_HINT:
1134       g_value_set_boolean (value,
1135                            gtk_window_get_skip_taskbar_hint (window));
1136       break;
1137     case PROP_SKIP_PAGER_HINT:
1138       g_value_set_boolean (value,
1139                            gtk_window_get_skip_pager_hint (window));
1140       break;
1141     case PROP_URGENCY_HINT:
1142       g_value_set_boolean (value,
1143                            gtk_window_get_urgency_hint (window));
1144       break;
1145     case PROP_ACCEPT_FOCUS:
1146       g_value_set_boolean (value,
1147                            gtk_window_get_accept_focus (window));
1148       break;
1149     case PROP_FOCUS_ON_MAP:
1150       g_value_set_boolean (value,
1151                            gtk_window_get_focus_on_map (window));
1152       break;
1153     case PROP_DECORATED:
1154       g_value_set_boolean (value, gtk_window_get_decorated (window));
1155       break;
1156     case PROP_DELETABLE:
1157       g_value_set_boolean (value, gtk_window_get_deletable (window));
1158       break;
1159     case PROP_GRAVITY:
1160       g_value_set_enum (value, gtk_window_get_gravity (window));
1161       break;
1162     case PROP_TRANSIENT_FOR:
1163       g_value_set_object (value, gtk_window_get_transient_for (window));
1164       break;
1165     case PROP_OPACITY:
1166       g_value_set_double (value, gtk_window_get_opacity (window));
1167       break;
1168     default:
1169       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1170       break;
1171     }
1172 }
1173
1174 static void
1175 gtk_window_buildable_interface_init (GtkBuildableIface *iface)
1176 {
1177   parent_buildable_iface = g_type_interface_peek_parent (iface);
1178   iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
1179   iface->parser_finished = gtk_window_buildable_parser_finished;
1180   iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
1181   iface->custom_finished = gtk_window_buildable_custom_finished;
1182 }
1183
1184 static void
1185 gtk_window_buildable_set_buildable_property (GtkBuildable        *buildable,
1186                                              GtkBuilder          *builder,
1187                                              const gchar         *name,
1188                                              const GValue        *value)
1189 {
1190   GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (buildable);
1191
1192   if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
1193     priv->builder_visible = TRUE;
1194   else
1195     parent_buildable_iface->set_buildable_property (buildable, builder, name, value);
1196 }
1197
1198 static void
1199 gtk_window_buildable_parser_finished (GtkBuildable *buildable,
1200                                       GtkBuilder   *builder)
1201 {
1202   GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (buildable);
1203   GObject *object;
1204   GSList *accels, *l;
1205
1206   if (priv->builder_visible)
1207     gtk_widget_show (GTK_WIDGET (buildable));
1208
1209   accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
1210   for (l = accels; l; l = l->next)
1211     {
1212       object = gtk_builder_get_object (builder, l->data);
1213       if (!object)
1214         {
1215           g_warning ("Unknown accel group %s specified in window %s",
1216                      (const gchar*)l->data, gtk_buildable_get_name (buildable));
1217           continue;
1218         }
1219       gtk_window_add_accel_group (GTK_WINDOW (buildable),
1220                                   GTK_ACCEL_GROUP (object));
1221       g_free (l->data);
1222     }
1223
1224   g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
1225
1226   parent_buildable_iface->parser_finished (buildable, builder);
1227 }
1228
1229 typedef struct {
1230   GObject *object;
1231   GSList *items;
1232 } GSListSubParserData;
1233
1234 static void
1235 window_start_element (GMarkupParseContext *context,
1236                           const gchar         *element_name,
1237                           const gchar        **names,
1238                           const gchar        **values,
1239                           gpointer            user_data,
1240                           GError            **error)
1241 {
1242   guint i;
1243   GSListSubParserData *data = (GSListSubParserData*)user_data;
1244
1245   if (strcmp (element_name, "group") == 0)
1246     {
1247       for (i = 0; names[i]; i++)
1248         {
1249           if (strcmp (names[i], "name") == 0)
1250             data->items = g_slist_prepend (data->items, g_strdup (values[i]));
1251         }
1252     }
1253   else if (strcmp (element_name, "accel-groups") == 0)
1254     return;
1255   else
1256     g_warning ("Unsupported tag type for GtkWindow: %s\n",
1257                element_name);
1258
1259 }
1260
1261 static const GMarkupParser window_parser =
1262   {
1263     window_start_element
1264   };
1265
1266 static gboolean
1267 gtk_window_buildable_custom_tag_start (GtkBuildable  *buildable,
1268                                        GtkBuilder    *builder,
1269                                        GObject       *child,
1270                                        const gchar   *tagname,
1271                                        GMarkupParser *parser,
1272                                        gpointer      *data)
1273 {
1274   GSListSubParserData *parser_data;
1275
1276   if (parent_buildable_iface->custom_tag_start (buildable, builder, child, 
1277                                                 tagname, parser, data))
1278     return TRUE;
1279
1280   if (strcmp (tagname, "accel-groups") == 0)
1281     {
1282       parser_data = g_slice_new0 (GSListSubParserData);
1283       parser_data->items = NULL;
1284       parser_data->object = G_OBJECT (buildable);
1285
1286       *parser = window_parser;
1287       *data = parser_data;
1288       return TRUE;
1289     }
1290
1291   return FALSE;
1292 }
1293
1294 static void
1295 gtk_window_buildable_custom_finished (GtkBuildable  *buildable,
1296                                           GtkBuilder    *builder,
1297                                           GObject       *child,
1298                                           const gchar   *tagname,
1299                                           gpointer       user_data)
1300 {
1301   GSListSubParserData *data;
1302
1303   parent_buildable_iface->custom_finished (buildable, builder, child, 
1304                                            tagname, user_data);
1305
1306   if (strcmp (tagname, "accel-groups") != 0)
1307     return;
1308   
1309   data = (GSListSubParserData*)user_data;
1310
1311   g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels, 
1312                            data->items, (GDestroyNotify) g_slist_free);
1313
1314   g_slice_free (GSListSubParserData, data);
1315 }
1316
1317 /**
1318  * gtk_window_new:
1319  * @type: type of window
1320  * 
1321  * Creates a new #GtkWindow, which is a toplevel window that can
1322  * contain other widgets. Nearly always, the type of the window should
1323  * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
1324  * popup menu from scratch (which is a bad idea, just use #GtkMenu),
1325  * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
1326  * dialogs, though in some other toolkits dialogs are called "popups".
1327  * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
1328  * On X11, popup windows are not controlled by the <link
1329  * linkend="gtk-X11-arch">window manager</link>.
1330  *
1331  * If you simply want an undecorated window (no window borders), use
1332  * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
1333  * 
1334  * Return value: a new #GtkWindow.
1335  **/
1336 GtkWidget*
1337 gtk_window_new (GtkWindowType type)
1338 {
1339   GtkWindow *window;
1340
1341   g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
1342
1343   window = g_object_new (GTK_TYPE_WINDOW, NULL);
1344
1345   window->type = type;
1346
1347   return GTK_WIDGET (window);
1348 }
1349
1350 /**
1351  * gtk_window_set_title:
1352  * @window: a #GtkWindow
1353  * @title: title of the window
1354  * 
1355  * Sets the title of the #GtkWindow. The title of a window will be
1356  * displayed in its title bar; on the X Window System, the title bar
1357  * is rendered by the <link linkend="gtk-X11-arch">window
1358  * manager</link>, so exactly how the title appears to users may vary
1359  * according to a user's exact configuration. The title should help a
1360  * user distinguish this window from other windows they may have
1361  * open. A good title might include the application name and current
1362  * document filename, for example.
1363  * 
1364  **/
1365 void
1366 gtk_window_set_title (GtkWindow   *window,
1367                       const gchar *title)
1368 {
1369   char *new_title;
1370   
1371   g_return_if_fail (GTK_IS_WINDOW (window));
1372
1373   new_title = g_strdup (title);
1374   g_free (window->title);
1375   window->title = new_title;
1376
1377   if (GTK_WIDGET_REALIZED (window))
1378     {
1379       gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
1380
1381       gtk_decorated_window_set_title (window, title);
1382     }
1383
1384   g_object_notify (G_OBJECT (window), "title");
1385 }
1386
1387 /**
1388  * gtk_window_get_title:
1389  * @window: a #GtkWindow
1390  *
1391  * Retrieves the title of the window. See gtk_window_set_title().
1392  *
1393  * Return value: the title of the window, or %NULL if none has
1394  *    been set explicitely. The returned string is owned by the widget
1395  *    and must not be modified or freed.
1396  **/
1397 G_CONST_RETURN gchar *
1398 gtk_window_get_title (GtkWindow *window)
1399 {
1400   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1401
1402   return window->title;
1403 }
1404
1405 /**
1406  * gtk_window_set_wmclass:
1407  * @window: a #GtkWindow
1408  * @wmclass_name: window name hint
1409  * @wmclass_class: window class hint
1410  *
1411  * Don't use this function. It sets the X Window System "class" and
1412  * "name" hints for a window.  According to the ICCCM, you should
1413  * always set these to the same value for all windows in an
1414  * application, and GTK+ sets them to that value by default, so calling
1415  * this function is sort of pointless. However, you may want to call
1416  * gtk_window_set_role() on each window in your application, for the
1417  * benefit of the session manager. Setting the role allows the window
1418  * manager to restore window positions when loading a saved session.
1419  * 
1420  **/
1421 void
1422 gtk_window_set_wmclass (GtkWindow *window,
1423                         const gchar *wmclass_name,
1424                         const gchar *wmclass_class)
1425 {
1426   g_return_if_fail (GTK_IS_WINDOW (window));
1427
1428   g_free (window->wmclass_name);
1429   window->wmclass_name = g_strdup (wmclass_name);
1430
1431   g_free (window->wmclass_class);
1432   window->wmclass_class = g_strdup (wmclass_class);
1433
1434   if (GTK_WIDGET_REALIZED (window))
1435     g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1436 }
1437
1438 /**
1439  * gtk_window_set_role:
1440  * @window: a #GtkWindow
1441  * @role: unique identifier for the window to be used when restoring a session
1442  *
1443  * This function is only useful on X11, not with other GTK+ targets.
1444  * 
1445  * In combination with the window title, the window role allows a
1446  * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1447  * same" window when an application is restarted. So for example you
1448  * might set the "toolbox" role on your app's toolbox window, so that
1449  * when the user restarts their session, the window manager can put
1450  * the toolbox back in the same place.
1451  *
1452  * If a window already has a unique title, you don't need to set the
1453  * role, since the WM can use the title to identify the window when
1454  * restoring the session.
1455  * 
1456  **/
1457 void
1458 gtk_window_set_role (GtkWindow   *window,
1459                      const gchar *role)
1460 {
1461   char *new_role;
1462   
1463   g_return_if_fail (GTK_IS_WINDOW (window));
1464
1465   new_role = g_strdup (role);
1466   g_free (window->wm_role);
1467   window->wm_role = new_role;
1468
1469   if (GTK_WIDGET_REALIZED (window))
1470     gdk_window_set_role (GTK_WIDGET (window)->window, window->wm_role);
1471
1472   g_object_notify (G_OBJECT (window), "role");
1473 }
1474
1475 /**
1476  * gtk_window_set_startup_id:
1477  * @window: a #GtkWindow
1478  * @startup_id: a string with startup-notification identifier
1479  *
1480  * Startup notification identifiers are used by desktop environment to 
1481  * track application startup, to provide user feedback and other 
1482  * features. This function changes the corresponding property on the
1483  * underlying GdkWindow. Normally, startup identifier is managed 
1484  * automatically and you should only use this function in special cases
1485  * like transferring focus from other processes. You should use this
1486  * function before calling gtk_window_present() or any equivalent
1487  * function generating a window map event.
1488  *
1489  * This function is only useful on X11, not with other GTK+ targets.
1490  * 
1491  * Since: 2.12
1492  **/
1493 void
1494 gtk_window_set_startup_id (GtkWindow   *window,
1495                            const gchar *startup_id)
1496 {
1497   GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
1498
1499   g_return_if_fail (GTK_IS_WINDOW (window));
1500   
1501   g_free (priv->startup_id);
1502   priv->startup_id = g_strdup (startup_id);
1503
1504   if (GTK_WIDGET_REALIZED (window))
1505     {
1506       guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
1507
1508 #ifdef GDK_WINDOWING_X11
1509       if (timestamp != GDK_CURRENT_TIME)
1510         gdk_x11_window_set_user_time (GTK_WIDGET (window)->window, timestamp);
1511 #endif
1512
1513       /* Here we differentiate real and "fake" startup notification IDs,
1514        * constructed on purpose just to pass interaction timestamp
1515        */
1516       if (startup_id_is_fake (priv->startup_id))
1517         gtk_window_present_with_time (window, timestamp);
1518       else 
1519         {
1520           gdk_window_set_startup_id (GTK_WIDGET (window)->window,
1521                                      priv->startup_id);
1522           
1523           /* If window is mapped, terminate the startup-notification too */
1524           if (GTK_WIDGET_MAPPED (window) && !disable_startup_notification)
1525             gdk_notify_startup_complete_with_id (priv->startup_id);
1526         }
1527     }
1528
1529   g_object_notify (G_OBJECT (window), "startup-id");
1530 }
1531
1532 /**
1533  * gtk_window_get_role:
1534  * @window: a #GtkWindow
1535  *
1536  * Returns the role of the window. See gtk_window_set_role() for
1537  * further explanation.
1538  *
1539  * Return value: the role of the window if set, or %NULL. The
1540  *   returned is owned by the widget and must not be modified
1541  *   or freed.
1542  **/
1543 G_CONST_RETURN gchar *
1544 gtk_window_get_role (GtkWindow *window)
1545 {
1546   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1547
1548   return window->wm_role;
1549 }
1550
1551 /**
1552  * gtk_window_set_focus:
1553  * @window: a #GtkWindow
1554  * @focus: widget to be the new focus widget, or %NULL to unset
1555  *   any focus widget for the toplevel window.
1556  *
1557  * If @focus is not the current focus widget, and is focusable, sets
1558  * it as the focus widget for the window. If @focus is %NULL, unsets
1559  * the focus widget for this window. To set the focus to a particular
1560  * widget in the toplevel, it is usually more convenient to use
1561  * gtk_widget_grab_focus() instead of this function.
1562  **/
1563 void
1564 gtk_window_set_focus (GtkWindow *window,
1565                       GtkWidget *focus)
1566 {
1567   g_return_if_fail (GTK_IS_WINDOW (window));
1568   if (focus)
1569     {
1570       g_return_if_fail (GTK_IS_WIDGET (focus));
1571       g_return_if_fail (GTK_WIDGET_CAN_FOCUS (focus));
1572     }
1573
1574   if (focus)
1575     gtk_widget_grab_focus (focus);
1576   else
1577     {
1578       /* Clear the existing focus chain, so that when we focus into
1579        * the window again, we start at the beginnning.
1580        */
1581       GtkWidget *widget = window->focus_widget;
1582       if (widget)
1583         {
1584           while (widget->parent)
1585             {
1586               widget = widget->parent;
1587               gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1588             }
1589         }
1590       
1591       _gtk_window_internal_set_focus (window, NULL);
1592     }
1593 }
1594
1595 void
1596 _gtk_window_internal_set_focus (GtkWindow *window,
1597                                 GtkWidget *focus)
1598 {
1599   g_return_if_fail (GTK_IS_WINDOW (window));
1600
1601   if ((window->focus_widget != focus) ||
1602       (focus && !GTK_WIDGET_HAS_FOCUS (focus)))
1603     g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1604 }
1605
1606 /**
1607  * gtk_window_set_default:
1608  * @window: a #GtkWindow
1609  * @default_widget: widget to be the default, or %NULL to unset the
1610  *                  default widget for the toplevel.
1611  *
1612  * The default widget is the widget that's activated when the user
1613  * presses Enter in a dialog (for example). This function sets or
1614  * unsets the default widget for a #GtkWindow about. When setting
1615  * (rather than unsetting) the default widget it's generally easier to
1616  * call gtk_widget_grab_focus() on the widget. Before making a widget
1617  * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1618  * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1619  **/
1620 void
1621 gtk_window_set_default (GtkWindow *window,
1622                         GtkWidget *default_widget)
1623 {
1624   g_return_if_fail (GTK_IS_WINDOW (window));
1625
1626   if (default_widget)
1627     g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
1628   
1629   if (window->default_widget != default_widget)
1630     {
1631       GtkWidget *old_default_widget = NULL;
1632       
1633       if (default_widget)
1634         g_object_ref (default_widget);
1635       
1636       if (window->default_widget)
1637         {
1638           old_default_widget = window->default_widget;
1639           
1640           if (window->focus_widget != window->default_widget ||
1641               !GTK_WIDGET_RECEIVES_DEFAULT (window->default_widget))
1642             GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1643           gtk_widget_queue_draw (window->default_widget);
1644         }
1645
1646       window->default_widget = default_widget;
1647
1648       if (window->default_widget)
1649         {
1650           if (window->focus_widget == NULL ||
1651               !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))
1652             GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1653           gtk_widget_queue_draw (window->default_widget);
1654         }
1655
1656       if (old_default_widget)
1657         g_object_notify (G_OBJECT (old_default_widget), "has-default");
1658       
1659       if (default_widget)
1660         {
1661           g_object_notify (G_OBJECT (default_widget), "has-default");
1662           g_object_unref (default_widget);
1663         }
1664     }
1665 }
1666
1667 /**
1668  * gtk_window_get_default_widget:
1669  * @window: a #GtkWindow
1670  *
1671  * Returns the default widget for @window. See gtk_window_set_default()
1672  * for more details.
1673  *
1674  * Returns: the default widget, or %NULL if there is none.
1675  *
1676  * Since: 2.14
1677  **/
1678 GtkWidget *
1679 gtk_window_get_default_widget (GtkWindow *window)
1680 {
1681   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1682
1683   return window->default_widget;
1684 }
1685
1686 static void
1687 gtk_window_set_policy_internal (GtkWindow *window,
1688                                 gboolean   allow_shrink,
1689                                 gboolean   allow_grow,
1690                                 gboolean   auto_shrink)
1691 {
1692   window->allow_shrink = (allow_shrink != FALSE);
1693   window->allow_grow = (allow_grow != FALSE);
1694
1695   g_object_freeze_notify (G_OBJECT (window));
1696   g_object_notify (G_OBJECT (window), "allow-shrink");
1697   g_object_notify (G_OBJECT (window), "allow-grow");
1698   g_object_notify (G_OBJECT (window), "resizable");
1699   g_object_thaw_notify (G_OBJECT (window));
1700
1701   gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
1702 }
1703
1704 void
1705 gtk_window_set_policy (GtkWindow *window,
1706                        gboolean   allow_shrink,
1707                        gboolean   allow_grow,
1708                        gboolean   auto_shrink)
1709 {
1710   g_return_if_fail (GTK_IS_WINDOW (window));
1711
1712   gtk_window_set_policy_internal (window, allow_shrink, allow_grow, auto_shrink);
1713 }
1714
1715 static gboolean
1716 handle_keys_changed (gpointer data)
1717 {
1718   GtkWindow *window;
1719
1720   window = GTK_WINDOW (data);
1721
1722   if (window->keys_changed_handler)
1723     {
1724       g_source_remove (window->keys_changed_handler);
1725       window->keys_changed_handler = 0;
1726     }
1727
1728   g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1729   
1730   return FALSE;
1731 }
1732
1733 static void
1734 gtk_window_notify_keys_changed (GtkWindow *window)
1735 {
1736   if (!window->keys_changed_handler)
1737     window->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window);
1738 }
1739
1740 /**
1741  * gtk_window_add_accel_group:
1742  * @window: window to attach accelerator group to
1743  * @accel_group: a #GtkAccelGroup
1744  *
1745  * Associate @accel_group with @window, such that calling
1746  * gtk_accel_groups_activate() on @window will activate accelerators
1747  * in @accel_group.
1748  **/
1749 void
1750 gtk_window_add_accel_group (GtkWindow     *window,
1751                             GtkAccelGroup *accel_group)
1752 {
1753   g_return_if_fail (GTK_IS_WINDOW (window));
1754   g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1755
1756   _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1757   g_signal_connect_object (accel_group, "accel-changed",
1758                            G_CALLBACK (gtk_window_notify_keys_changed),
1759                            window, G_CONNECT_SWAPPED);
1760   gtk_window_notify_keys_changed (window);
1761 }
1762
1763 /**
1764  * gtk_window_remove_accel_group:
1765  * @window: a #GtkWindow
1766  * @accel_group: a #GtkAccelGroup
1767  *
1768  * Reverses the effects of gtk_window_add_accel_group().
1769  **/
1770 void
1771 gtk_window_remove_accel_group (GtkWindow     *window,
1772                                GtkAccelGroup *accel_group)
1773 {
1774   g_return_if_fail (GTK_IS_WINDOW (window));
1775   g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1776
1777   g_signal_handlers_disconnect_by_func (accel_group,
1778                                         gtk_window_notify_keys_changed,
1779                                         window);
1780   _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1781   gtk_window_notify_keys_changed (window);
1782 }
1783
1784 static GtkMnemonicHash *
1785 gtk_window_get_mnemonic_hash (GtkWindow *window,
1786                               gboolean   create)
1787 {
1788   GtkWindowPrivate *private = GTK_WINDOW_GET_PRIVATE (window);
1789   if (!private->mnemonic_hash && create)
1790     private->mnemonic_hash = _gtk_mnemonic_hash_new ();
1791   
1792   return private->mnemonic_hash;
1793 }
1794
1795 /**
1796  * gtk_window_add_mnemonic:
1797  * @window: a #GtkWindow
1798  * @keyval: the mnemonic
1799  * @target: the widget that gets activated by the mnemonic
1800  *
1801  * Adds a mnemonic to this window.
1802  */
1803 void
1804 gtk_window_add_mnemonic (GtkWindow *window,
1805                          guint      keyval,
1806                          GtkWidget *target)
1807 {
1808   g_return_if_fail (GTK_IS_WINDOW (window));
1809   g_return_if_fail (GTK_IS_WIDGET (target));
1810
1811   _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
1812                           keyval, target);
1813   gtk_window_notify_keys_changed (window);
1814 }
1815
1816 /**
1817  * gtk_window_remove_mnemonic:
1818  * @window: a #GtkWindow
1819  * @keyval: the mnemonic
1820  * @target: the widget that gets activated by the mnemonic
1821  *
1822  * Removes a mnemonic from this window.
1823  */
1824 void
1825 gtk_window_remove_mnemonic (GtkWindow *window,
1826                             guint      keyval,
1827                             GtkWidget *target)
1828 {
1829   g_return_if_fail (GTK_IS_WINDOW (window));
1830   g_return_if_fail (GTK_IS_WIDGET (target));
1831   
1832   _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
1833                              keyval, target);
1834   gtk_window_notify_keys_changed (window);
1835 }
1836
1837 /**
1838  * gtk_window_mnemonic_activate:
1839  * @window: a #GtkWindow
1840  * @keyval: the mnemonic
1841  * @modifier: the modifiers 
1842  * @returns: %TRUE if the activation is done. 
1843  * 
1844  * Activates the targets associated with the mnemonic.
1845  */
1846 gboolean
1847 gtk_window_mnemonic_activate (GtkWindow      *window,
1848                               guint           keyval,
1849                               GdkModifierType modifier)
1850 {
1851   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1852
1853   if (window->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
1854       {
1855         GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
1856         if (mnemonic_hash)
1857           return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
1858       }
1859
1860   return FALSE;
1861 }
1862
1863 /**
1864  * gtk_window_set_mnemonic_modifier:
1865  * @window: a #GtkWindow
1866  * @modifier: the modifier mask used to activate
1867  *               mnemonics on this window.
1868  *
1869  * Sets the mnemonic modifier for this window. 
1870  **/
1871 void
1872 gtk_window_set_mnemonic_modifier (GtkWindow      *window,
1873                                   GdkModifierType modifier)
1874 {
1875   g_return_if_fail (GTK_IS_WINDOW (window));
1876   g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
1877
1878   window->mnemonic_modifier = modifier;
1879   gtk_window_notify_keys_changed (window);
1880 }
1881
1882 /**
1883  * gtk_window_get_mnemonic_modifier:
1884  * @window: a #GtkWindow
1885  *
1886  * Returns the mnemonic modifier for this window. See
1887  * gtk_window_set_mnemonic_modifier().
1888  *
1889  * Return value: the modifier mask used to activate
1890  *               mnemonics on this window.
1891  **/
1892 GdkModifierType
1893 gtk_window_get_mnemonic_modifier (GtkWindow *window)
1894 {
1895   g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
1896
1897   return window->mnemonic_modifier;
1898 }
1899
1900 /**
1901  * gtk_window_set_position:
1902  * @window: a #GtkWindow.
1903  * @position: a position constraint.
1904  *
1905  * Sets a position constraint for this window. If the old or new
1906  * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
1907  * the window to be repositioned to satisfy the new constraint. 
1908  **/
1909 void
1910 gtk_window_set_position (GtkWindow         *window,
1911                          GtkWindowPosition  position)
1912 {
1913   g_return_if_fail (GTK_IS_WINDOW (window));
1914
1915   if (position == GTK_WIN_POS_CENTER_ALWAYS ||
1916       window->position == GTK_WIN_POS_CENTER_ALWAYS)
1917     {
1918       GtkWindowGeometryInfo *info;
1919
1920       info = gtk_window_get_geometry_info (window, TRUE);
1921
1922       /* this flag causes us to re-request the CENTER_ALWAYS
1923        * constraint in gtk_window_move_resize(), see
1924        * comment in that function.
1925        */
1926       info->position_constraints_changed = TRUE;
1927
1928       gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
1929     }
1930
1931   window->position = position;
1932   
1933   g_object_notify (G_OBJECT (window), "window-position");
1934 }
1935
1936 /**
1937  * gtk_window_activate_focus:
1938  * @window: a #GtkWindow
1939  * 
1940  * Activates the current focused widget within the window.
1941  * 
1942  * Return value: %TRUE if a widget got activated.
1943  **/
1944 gboolean 
1945 gtk_window_activate_focus (GtkWindow *window)
1946 {
1947   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1948
1949   if (window->focus_widget && GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1950     return gtk_widget_activate (window->focus_widget);
1951
1952   return FALSE;
1953 }
1954
1955 /**
1956  * gtk_window_get_focus:
1957  * @window: a #GtkWindow
1958  * 
1959  * Retrieves the current focused widget within the window.
1960  * Note that this is the widget that would have the focus
1961  * if the toplevel window focused; if the toplevel window
1962  * is not focused then  <literal>GTK_WIDGET_HAS_FOCUS (widget)</literal> will
1963  * not be %TRUE for the widget. 
1964  * 
1965  * Return value: the currently focused widget, or %NULL if there is none.
1966  **/
1967 GtkWidget *
1968 gtk_window_get_focus (GtkWindow *window)
1969 {
1970   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1971
1972   return window->focus_widget;
1973 }
1974
1975 /**
1976  * gtk_window_activate_default:
1977  * @window: a #GtkWindow
1978  * 
1979  * Activates the default widget for the window, unless the current 
1980  * focused widget has been configured to receive the default action 
1981  * (see #GTK_RECEIVES_DEFAULT in #GtkWidgetFlags), in which case the
1982  * focused widget is activated. 
1983  * 
1984  * Return value: %TRUE if a widget got activated.
1985  **/
1986 gboolean
1987 gtk_window_activate_default (GtkWindow *window)
1988 {
1989   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1990
1991   if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
1992       (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1993     return gtk_widget_activate (window->default_widget);
1994   else if (window->focus_widget && GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1995     return gtk_widget_activate (window->focus_widget);
1996
1997   return FALSE;
1998 }
1999
2000 /**
2001  * gtk_window_set_modal:
2002  * @window: a #GtkWindow
2003  * @modal: whether the window is modal
2004  * 
2005  * Sets a window modal or non-modal. Modal windows prevent interaction
2006  * with other windows in the same application. To keep modal dialogs
2007  * on top of main application windows, use
2008  * gtk_window_set_transient_for() to make the dialog transient for the
2009  * parent; most <link linkend="gtk-X11-arch">window managers</link>
2010  * will then disallow lowering the dialog below the parent.
2011  * 
2012  * 
2013  **/
2014 void
2015 gtk_window_set_modal (GtkWindow *window,
2016                       gboolean   modal)
2017 {
2018   g_return_if_fail (GTK_IS_WINDOW (window));
2019
2020   modal = modal != FALSE;
2021   if (window->modal == modal)
2022     return;
2023   
2024   window->modal = modal;
2025   
2026   /* adjust desired modality state */
2027   if (GTK_WIDGET_REALIZED (window))
2028     {
2029       GtkWidget *widget = GTK_WIDGET (window);
2030       
2031       if (window->modal)
2032         gdk_window_set_modal_hint (widget->window, TRUE);
2033       else
2034         gdk_window_set_modal_hint (widget->window, FALSE);
2035     }
2036
2037   if (GTK_WIDGET_VISIBLE (window))
2038     {
2039       if (window->modal)
2040         gtk_grab_add (GTK_WIDGET (window));
2041       else
2042         gtk_grab_remove (GTK_WIDGET (window));
2043     }
2044
2045   g_object_notify (G_OBJECT (window), "modal");
2046 }
2047
2048 /**
2049  * gtk_window_get_modal:
2050  * @window: a #GtkWindow
2051  * 
2052  * Returns whether the window is modal. See gtk_window_set_modal().
2053  *
2054  * Return value: %TRUE if the window is set to be modal and
2055  *               establishes a grab when shown
2056  **/
2057 gboolean
2058 gtk_window_get_modal (GtkWindow *window)
2059 {
2060   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2061
2062   return window->modal;
2063 }
2064
2065 /**
2066  * gtk_window_list_toplevels:
2067  * 
2068  * Returns a list of all existing toplevel windows. The widgets
2069  * in the list are not individually referenced. If you want
2070  * to iterate through the list and perform actions involving
2071  * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
2072  * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
2073  * then unref all the widgets afterwards.
2074  * 
2075  * Return value: list of toplevel widgets
2076  **/
2077 GList*
2078 gtk_window_list_toplevels (void)
2079 {
2080   GList *list = NULL;
2081   GSList *slist;
2082
2083   for (slist = toplevel_list; slist; slist = slist->next)
2084     list = g_list_prepend (list, slist->data);
2085
2086   return list;
2087 }
2088
2089 void
2090 gtk_window_add_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2091 {
2092   GList *embedded_windows;
2093
2094   g_return_if_fail (GTK_IS_WINDOW (window));
2095
2096   embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2097   if (embedded_windows)
2098     g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2099   embedded_windows = g_list_prepend (embedded_windows,
2100                                      GUINT_TO_POINTER (xid));
2101
2102   g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded, 
2103                            embedded_windows,
2104                            embedded_windows ?
2105                            (GDestroyNotify) g_list_free : NULL);
2106 }
2107
2108 void
2109 gtk_window_remove_embedded_xid (GtkWindow *window, GdkNativeWindow xid)
2110 {
2111   GList *embedded_windows;
2112   GList *node;
2113
2114   g_return_if_fail (GTK_IS_WINDOW (window));
2115   
2116   embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded);
2117   if (embedded_windows)
2118     g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded);
2119
2120   node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
2121   if (node)
2122     {
2123       embedded_windows = g_list_remove_link (embedded_windows, node);
2124       g_list_free_1 (node);
2125     }
2126   
2127   g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded,
2128                            embedded_windows,
2129                            embedded_windows ?
2130                            (GDestroyNotify) g_list_free : NULL);
2131 }
2132
2133 void       
2134 _gtk_window_reposition (GtkWindow *window,
2135                         gint       x,
2136                         gint       y)
2137 {
2138   g_return_if_fail (GTK_IS_WINDOW (window));
2139
2140   gtk_window_move (window, x, y);
2141 }
2142
2143 static void
2144 gtk_window_dispose (GObject *object)
2145 {
2146   GtkWindow *window = GTK_WINDOW (object);
2147
2148   gtk_window_set_focus (window, NULL);
2149   gtk_window_set_default (window, NULL);
2150
2151   G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
2152 }
2153
2154 static void
2155 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
2156 {
2157   gtk_widget_destroy (GTK_WIDGET (child));
2158 }
2159
2160 static void
2161 connect_parent_destroyed (GtkWindow *window)
2162 {
2163   if (window->transient_parent)
2164     {
2165       g_signal_connect (window->transient_parent,
2166                         "destroy",
2167                         G_CALLBACK (parent_destroyed_callback),
2168                         window);
2169     }  
2170 }
2171
2172 static void
2173 disconnect_parent_destroyed (GtkWindow *window)
2174 {
2175   if (window->transient_parent)
2176     {
2177       g_signal_handlers_disconnect_by_func (window->transient_parent,
2178                                             parent_destroyed_callback,
2179                                             window);
2180     }
2181 }
2182
2183 static void
2184 gtk_window_transient_parent_realized (GtkWidget *parent,
2185                                       GtkWidget *window)
2186 {
2187   if (GTK_WIDGET_REALIZED (window))
2188     gdk_window_set_transient_for (window->window, parent->window);
2189 }
2190
2191 static void
2192 gtk_window_transient_parent_unrealized (GtkWidget *parent,
2193                                         GtkWidget *window)
2194 {
2195   if (GTK_WIDGET_REALIZED (window))
2196     gdk_property_delete (window->window, 
2197                          gdk_atom_intern_static_string ("WM_TRANSIENT_FOR"));
2198 }
2199
2200 static void
2201 gtk_window_transient_parent_screen_changed (GtkWindow   *parent,
2202                                             GParamSpec  *pspec,
2203                                             GtkWindow   *window)
2204 {
2205   gtk_window_set_screen (window, parent->screen);
2206 }
2207
2208 static void       
2209 gtk_window_unset_transient_for  (GtkWindow *window)
2210 {
2211   GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
2212   
2213   if (window->transient_parent)
2214     {
2215       g_signal_handlers_disconnect_by_func (window->transient_parent,
2216                                             gtk_window_transient_parent_realized,
2217                                             window);
2218       g_signal_handlers_disconnect_by_func (window->transient_parent,
2219                                             gtk_window_transient_parent_unrealized,
2220                                             window);
2221       g_signal_handlers_disconnect_by_func (window->transient_parent,
2222                                             gtk_window_transient_parent_screen_changed,
2223                                             window);
2224       g_signal_handlers_disconnect_by_func (window->transient_parent,
2225                                             gtk_widget_destroyed,
2226                                             &window->transient_parent);
2227
2228       if (window->destroy_with_parent)
2229         disconnect_parent_destroyed (window);
2230       
2231       window->transient_parent = NULL;
2232
2233       if (priv->transient_parent_group)
2234         {
2235           priv->transient_parent_group = FALSE;
2236           gtk_window_group_remove_window (window->group,
2237                                           window);
2238         }
2239     }
2240 }
2241
2242 /**
2243  * gtk_window_set_transient_for:
2244  * @window: a #GtkWindow
2245  * @parent: parent window
2246  *
2247  * Dialog windows should be set transient for the main application
2248  * window they were spawned from. This allows <link
2249  * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
2250  * dialog on top of the main window, or center the dialog over the
2251  * main window. gtk_dialog_new_with_buttons() and other convenience
2252  * functions in GTK+ will sometimes call
2253  * gtk_window_set_transient_for() on your behalf.
2254  *
2255  * On Windows, this function puts the child window on top of the parent, 
2256  * much as the window manager would have done on X.
2257  * 
2258  **/
2259 void       
2260 gtk_window_set_transient_for  (GtkWindow *window, 
2261                                GtkWindow *parent)
2262 {
2263   GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
2264   
2265   g_return_if_fail (GTK_IS_WINDOW (window));
2266   g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2267   g_return_if_fail (window != parent);
2268
2269   if (window->transient_parent)
2270     {
2271       if (GTK_WIDGET_REALIZED (window) && 
2272           GTK_WIDGET_REALIZED (window->transient_parent) && 
2273           (!parent || !GTK_WIDGET_REALIZED (parent)))
2274         gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
2275                                                 GTK_WIDGET (window));
2276
2277       gtk_window_unset_transient_for (window);
2278     }
2279
2280   window->transient_parent = parent;
2281   
2282   if (parent)
2283     {
2284       g_signal_connect (parent, "destroy",
2285                         G_CALLBACK (gtk_widget_destroyed),
2286                         &window->transient_parent);
2287       g_signal_connect (parent, "realize",
2288                         G_CALLBACK (gtk_window_transient_parent_realized),
2289                         window);
2290       g_signal_connect (parent, "unrealize",
2291                         G_CALLBACK (gtk_window_transient_parent_unrealized),
2292                         window);
2293       g_signal_connect (parent, "notify::screen",
2294                         G_CALLBACK (gtk_window_transient_parent_screen_changed),
2295                         window);
2296       
2297       gtk_window_set_screen (window, parent->screen);
2298
2299       if (window->destroy_with_parent)
2300         connect_parent_destroyed (window);
2301       
2302       if (GTK_WIDGET_REALIZED (window) &&
2303           GTK_WIDGET_REALIZED (parent))
2304         gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2305                                               GTK_WIDGET (window));
2306
2307       if (parent->group)
2308         {
2309           gtk_window_group_add_window (parent->group, window);
2310           priv->transient_parent_group = TRUE;
2311         }
2312     }
2313 }
2314
2315 /**
2316  * gtk_window_get_transient_for:
2317  * @window: a #GtkWindow
2318  *
2319  * Fetches the transient parent for this window. See
2320  * gtk_window_set_transient_for().
2321  *
2322  * Return value: the transient parent for this window, or %NULL
2323  *    if no transient parent has been set.
2324  **/
2325 GtkWindow *
2326 gtk_window_get_transient_for (GtkWindow *window)
2327 {
2328   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2329
2330   return window->transient_parent;
2331 }
2332
2333 /**
2334  * gtk_window_set_opacity:
2335  * @window: a #GtkWindow
2336  * @opacity: desired opacity, between 0 and 1
2337  *
2338  * Request the windowing system to make @window partially transparent,
2339  * with opacity 0 being fully transparent and 1 fully opaque. (Values
2340  * of the opacity parameter are clamped to the [0,1] range.) On X11
2341  * this has any effect only on X screens with a compositing manager
2342  * running. See gtk_widget_is_composited(). On Windows it should work
2343  * always.
2344  * 
2345  * Note that setting a window's opacity after the window has been
2346  * shown causes it to flicker once on Windows.
2347  *
2348  * Since: 2.12
2349  **/
2350 void       
2351 gtk_window_set_opacity  (GtkWindow *window, 
2352                          gdouble    opacity)
2353 {
2354   GtkWindowPrivate *priv;
2355   
2356   g_return_if_fail (GTK_IS_WINDOW (window));
2357
2358   priv = GTK_WINDOW_GET_PRIVATE (window); 
2359
2360   if (opacity < 0.0)
2361     opacity = 0.0;
2362   else if (opacity > 1.0)
2363     opacity = 1.0;
2364
2365   priv->opacity_set = TRUE;
2366   priv->opacity = opacity;
2367
2368   if (GTK_WIDGET_REALIZED (window))
2369     gdk_window_set_opacity (GTK_WIDGET (window)->window, priv->opacity);
2370 }
2371
2372 /**
2373  * gtk_window_get_opacity:
2374  * @window: a #GtkWindow
2375  *
2376  * Fetches the requested opacity for this window. See
2377  * gtk_window_set_opacity().
2378  *
2379  * Return value: the requested opacity for this window.
2380  *
2381  * Since: 2.12
2382  **/
2383 gdouble
2384 gtk_window_get_opacity (GtkWindow *window)
2385 {
2386   GtkWindowPrivate *priv;
2387   
2388   g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2389
2390   priv = GTK_WINDOW_GET_PRIVATE (window); 
2391
2392   return priv->opacity;
2393 }
2394
2395 /**
2396  * gtk_window_set_type_hint:
2397  * @window: a #GtkWindow
2398  * @hint: the window type
2399  *
2400  * By setting the type hint for the window, you allow the window
2401  * manager to decorate and handle the window in a way which is
2402  * suitable to the function of the window in your application.
2403  *
2404  * This function should be called before the window becomes visible.
2405  *
2406  * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2407  * will sometimes call gtk_window_set_type_hint() on your behalf.
2408  * 
2409  **/
2410 void
2411 gtk_window_set_type_hint (GtkWindow           *window, 
2412                           GdkWindowTypeHint    hint)
2413 {
2414   GtkWindowPrivate *priv;
2415
2416   g_return_if_fail (GTK_IS_WINDOW (window));
2417   g_return_if_fail (!GTK_WIDGET_VISIBLE (window));
2418
2419   priv = GTK_WINDOW_GET_PRIVATE (window);
2420
2421   if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2422     window->type_hint = hint;
2423   else
2424     window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2425
2426   priv->reset_type_hint = TRUE;
2427   priv->type_hint = hint;
2428 }
2429
2430 /**
2431  * gtk_window_get_type_hint:
2432  * @window: a #GtkWindow
2433  *
2434  * Gets the type hint for this window. See gtk_window_set_type_hint().
2435  *
2436  * Return value: the type hint for @window.
2437  **/
2438 GdkWindowTypeHint
2439 gtk_window_get_type_hint (GtkWindow *window)
2440 {
2441   GtkWindowPrivate *priv;
2442   
2443   g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2444
2445   priv = GTK_WINDOW_GET_PRIVATE (window);
2446   
2447   return priv->type_hint;
2448 }
2449
2450 /**
2451  * gtk_window_set_skip_taskbar_hint:
2452  * @window: a #GtkWindow 
2453  * @setting: %TRUE to keep this window from appearing in the task bar
2454  * 
2455  * Windows may set a hint asking the desktop environment not to display
2456  * the window in the task bar. This function sets this hint.
2457  * 
2458  * Since: 2.2
2459  **/
2460 void
2461 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2462                                   gboolean   setting)
2463 {
2464   GtkWindowPrivate *priv;
2465
2466   g_return_if_fail (GTK_IS_WINDOW (window));
2467   
2468   priv = GTK_WINDOW_GET_PRIVATE (window);
2469
2470   setting = setting != FALSE;
2471
2472   if (priv->skips_taskbar != setting)
2473     {
2474       priv->skips_taskbar = setting;
2475       if (GTK_WIDGET_REALIZED (window))
2476         gdk_window_set_skip_taskbar_hint (GTK_WIDGET (window)->window,
2477                                           priv->skips_taskbar);
2478       g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2479     }
2480 }
2481
2482 /**
2483  * gtk_window_get_skip_taskbar_hint:
2484  * @window: a #GtkWindow
2485  * 
2486  * Gets the value set by gtk_window_set_skip_taskbar_hint()
2487  * 
2488  * Return value: %TRUE if window shouldn't be in taskbar
2489  * 
2490  * Since: 2.2
2491  **/
2492 gboolean
2493 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2494 {
2495   GtkWindowPrivate *priv;
2496
2497   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2498   
2499   priv = GTK_WINDOW_GET_PRIVATE (window);
2500
2501   return priv->skips_taskbar;
2502 }
2503
2504 /**
2505  * gtk_window_set_skip_pager_hint:
2506  * @window: a #GtkWindow 
2507  * @setting: %TRUE to keep this window from appearing in the pager
2508  * 
2509  * Windows may set a hint asking the desktop environment not to display
2510  * the window in the pager. This function sets this hint.
2511  * (A "pager" is any desktop navigation tool such as a workspace
2512  * switcher that displays a thumbnail representation of the windows
2513  * on the screen.)
2514  * 
2515  * Since: 2.2
2516  **/
2517 void
2518 gtk_window_set_skip_pager_hint (GtkWindow *window,
2519                                 gboolean   setting)
2520 {
2521   GtkWindowPrivate *priv;
2522
2523   g_return_if_fail (GTK_IS_WINDOW (window));
2524   
2525   priv = GTK_WINDOW_GET_PRIVATE (window);
2526
2527   setting = setting != FALSE;
2528
2529   if (priv->skips_pager != setting)
2530     {
2531       priv->skips_pager = setting;
2532       if (GTK_WIDGET_REALIZED (window))
2533         gdk_window_set_skip_pager_hint (GTK_WIDGET (window)->window,
2534                                         priv->skips_pager);
2535       g_object_notify (G_OBJECT (window), "skip-pager-hint");
2536     }
2537 }
2538
2539 /**
2540  * gtk_window_get_skip_pager_hint:
2541  * @window: a #GtkWindow
2542  * 
2543  * Gets the value set by gtk_window_set_skip_pager_hint().
2544  * 
2545  * Return value: %TRUE if window shouldn't be in pager
2546  * 
2547  * Since: 2.2
2548  **/
2549 gboolean
2550 gtk_window_get_skip_pager_hint (GtkWindow *window)
2551 {
2552   GtkWindowPrivate *priv;
2553
2554   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2555   
2556   priv = GTK_WINDOW_GET_PRIVATE (window);
2557
2558   return priv->skips_pager;
2559 }
2560
2561 /**
2562  * gtk_window_set_urgency_hint:
2563  * @window: a #GtkWindow 
2564  * @setting: %TRUE to mark this window as urgent
2565  * 
2566  * Windows may set a hint asking the desktop environment to draw
2567  * the users attention to the window. This function sets this hint.
2568  * 
2569  * Since: 2.8
2570  **/
2571 void
2572 gtk_window_set_urgency_hint (GtkWindow *window,
2573                              gboolean   setting)
2574 {
2575   GtkWindowPrivate *priv;
2576
2577   g_return_if_fail (GTK_IS_WINDOW (window));
2578   
2579   priv = GTK_WINDOW_GET_PRIVATE (window);
2580
2581   setting = setting != FALSE;
2582
2583   if (priv->urgent != setting)
2584     {
2585       priv->urgent = setting;
2586       if (GTK_WIDGET_REALIZED (window))
2587         gdk_window_set_urgency_hint (GTK_WIDGET (window)->window,
2588                                      priv->urgent);
2589       g_object_notify (G_OBJECT (window), "urgency-hint");
2590     }
2591 }
2592
2593 /**
2594  * gtk_window_get_urgency_hint:
2595  * @window: a #GtkWindow
2596  * 
2597  * Gets the value set by gtk_window_set_urgency_hint()
2598  * 
2599  * Return value: %TRUE if window is urgent
2600  * 
2601  * Since: 2.8
2602  **/
2603 gboolean
2604 gtk_window_get_urgency_hint (GtkWindow *window)
2605 {
2606   GtkWindowPrivate *priv;
2607
2608   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2609   
2610   priv = GTK_WINDOW_GET_PRIVATE (window);
2611
2612   return priv->urgent;
2613 }
2614
2615 /**
2616  * gtk_window_set_accept_focus:
2617  * @window: a #GtkWindow 
2618  * @setting: %TRUE to let this window receive input focus
2619  * 
2620  * Windows may set a hint asking the desktop environment not to receive
2621  * the input focus. This function sets this hint.
2622  * 
2623  * Since: 2.4
2624  **/
2625 void
2626 gtk_window_set_accept_focus (GtkWindow *window,
2627                              gboolean   setting)
2628 {
2629   GtkWindowPrivate *priv;
2630
2631   g_return_if_fail (GTK_IS_WINDOW (window));
2632   
2633   priv = GTK_WINDOW_GET_PRIVATE (window);
2634
2635   setting = setting != FALSE;
2636
2637   if (priv->accept_focus != setting)
2638     {
2639       priv->accept_focus = setting;
2640       if (GTK_WIDGET_REALIZED (window))
2641         gdk_window_set_accept_focus (GTK_WIDGET (window)->window,
2642                                      priv->accept_focus);
2643       g_object_notify (G_OBJECT (window), "accept-focus");
2644     }
2645 }
2646
2647 /**
2648  * gtk_window_get_accept_focus:
2649  * @window: a #GtkWindow
2650  * 
2651  * Gets the value set by gtk_window_set_accept_focus().
2652  * 
2653  * Return value: %TRUE if window should receive the input focus
2654  * 
2655  * Since: 2.4
2656  **/
2657 gboolean
2658 gtk_window_get_accept_focus (GtkWindow *window)
2659 {
2660   GtkWindowPrivate *priv;
2661
2662   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2663   
2664   priv = GTK_WINDOW_GET_PRIVATE (window);
2665
2666   return priv->accept_focus;
2667 }
2668
2669 /**
2670  * gtk_window_set_focus_on_map:
2671  * @window: a #GtkWindow 
2672  * @setting: %TRUE to let this window receive input focus on map
2673  * 
2674  * Windows may set a hint asking the desktop environment not to receive
2675  * the input focus when the window is mapped.  This function sets this
2676  * hint.
2677  * 
2678  * Since: 2.6
2679  **/
2680 void
2681 gtk_window_set_focus_on_map (GtkWindow *window,
2682                              gboolean   setting)
2683 {
2684   GtkWindowPrivate *priv;
2685
2686   g_return_if_fail (GTK_IS_WINDOW (window));
2687   
2688   priv = GTK_WINDOW_GET_PRIVATE (window);
2689
2690   setting = setting != FALSE;
2691
2692   if (priv->focus_on_map != setting)
2693     {
2694       priv->focus_on_map = setting;
2695       if (GTK_WIDGET_REALIZED (window))
2696         gdk_window_set_focus_on_map (GTK_WIDGET (window)->window,
2697                                      priv->focus_on_map);
2698       g_object_notify (G_OBJECT (window), "focus-on-map");
2699     }
2700 }
2701
2702 /**
2703  * gtk_window_get_focus_on_map:
2704  * @window: a #GtkWindow
2705  * 
2706  * Gets the value set by gtk_window_set_focus_on_map().
2707  * 
2708  * Return value: %TRUE if window should receive the input focus when
2709  * mapped.
2710  * 
2711  * Since: 2.6
2712  **/
2713 gboolean
2714 gtk_window_get_focus_on_map (GtkWindow *window)
2715 {
2716   GtkWindowPrivate *priv;
2717
2718   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2719   
2720   priv = GTK_WINDOW_GET_PRIVATE (window);
2721
2722   return priv->focus_on_map;
2723 }
2724
2725 /**
2726  * gtk_window_set_destroy_with_parent:
2727  * @window: a #GtkWindow
2728  * @setting: whether to destroy @window with its transient parent
2729  * 
2730  * If @setting is %TRUE, then destroying the transient parent of @window
2731  * will also destroy @window itself. This is useful for dialogs that
2732  * shouldn't persist beyond the lifetime of the main window they're
2733  * associated with, for example.
2734  **/
2735 void
2736 gtk_window_set_destroy_with_parent  (GtkWindow *window,
2737                                      gboolean   setting)
2738 {
2739   g_return_if_fail (GTK_IS_WINDOW (window));
2740
2741   if (window->destroy_with_parent == (setting != FALSE))
2742     return;
2743
2744   if (window->destroy_with_parent)
2745     {
2746       disconnect_parent_destroyed (window);
2747     }
2748   else
2749     {
2750       connect_parent_destroyed (window);
2751     }
2752   
2753   window->destroy_with_parent = setting;
2754
2755   g_object_notify (G_OBJECT (window), "destroy-with-parent");
2756 }
2757
2758 /**
2759  * gtk_window_get_destroy_with_parent:
2760  * @window: a #GtkWindow
2761  * 
2762  * Returns whether the window will be destroyed with its transient parent. See
2763  * gtk_window_set_destroy_with_parent ().
2764  *
2765  * Return value: %TRUE if the window will be destroyed with its transient parent.
2766  **/
2767 gboolean
2768 gtk_window_get_destroy_with_parent (GtkWindow *window)
2769 {
2770   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2771
2772   return window->destroy_with_parent;
2773 }
2774
2775 static GtkWindowGeometryInfo*
2776 gtk_window_get_geometry_info (GtkWindow *window,
2777                               gboolean   create)
2778 {
2779   GtkWindowGeometryInfo *info;
2780
2781   info = window->geometry_info;
2782   if (!info && create)
2783     {
2784       info = g_new0 (GtkWindowGeometryInfo, 1);
2785
2786       info->default_width = -1;
2787       info->default_height = -1;
2788       info->resize_width = -1;
2789       info->resize_height = -1;
2790       info->initial_x = 0;
2791       info->initial_y = 0;
2792       info->initial_pos_set = FALSE;
2793       info->default_is_geometry = FALSE;
2794       info->position_constraints_changed = FALSE;
2795       info->last.configure_request.x = 0;
2796       info->last.configure_request.y = 0;
2797       info->last.configure_request.width = -1;
2798       info->last.configure_request.height = -1;
2799       info->widget = NULL;
2800       info->mask = 0;
2801       window->geometry_info = info;
2802     }
2803
2804   return info;
2805 }
2806
2807 /**
2808  * gtk_window_set_geometry_hints:
2809  * @window: a #GtkWindow
2810  * @geometry_widget: widget the geometry hints will be applied to
2811  * @geometry: struct containing geometry information
2812  * @geom_mask: mask indicating which struct fields should be paid attention to
2813  *
2814  * This function sets up hints about how a window can be resized by
2815  * the user.  You can set a minimum and maximum size; allowed resize
2816  * increments (e.g. for xterm, you can only resize by the size of a
2817  * character); aspect ratios; and more. See the #GdkGeometry struct.
2818  * 
2819  **/
2820 void       
2821 gtk_window_set_geometry_hints (GtkWindow       *window,
2822                                GtkWidget       *geometry_widget,
2823                                GdkGeometry     *geometry,
2824                                GdkWindowHints   geom_mask)
2825 {
2826   GtkWindowGeometryInfo *info;
2827
2828   g_return_if_fail (GTK_IS_WINDOW (window));
2829   g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
2830
2831   info = gtk_window_get_geometry_info (window, TRUE);
2832   
2833   if (info->widget)
2834     g_signal_handlers_disconnect_by_func (info->widget,
2835                                           gtk_widget_destroyed,
2836                                           &info->widget);
2837   
2838   info->widget = geometry_widget;
2839   if (info->widget)
2840     g_signal_connect (geometry_widget, "destroy",
2841                       G_CALLBACK (gtk_widget_destroyed),
2842                       &info->widget);
2843
2844   if (geometry)
2845     info->geometry = *geometry;
2846
2847   /* We store gravity in window->gravity not in the hints. */
2848   info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
2849
2850   if (geom_mask & GDK_HINT_WIN_GRAVITY)
2851     {
2852       gtk_window_set_gravity (window, geometry->win_gravity);
2853     }
2854   
2855   gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2856 }
2857
2858 /**
2859  * gtk_window_set_decorated:
2860  * @window: a #GtkWindow
2861  * @setting: %TRUE to decorate the window
2862  *
2863  * By default, windows are decorated with a title bar, resize
2864  * controls, etc.  Some <link linkend="gtk-X11-arch">window
2865  * managers</link> allow GTK+ to disable these decorations, creating a
2866  * borderless window. If you set the decorated property to %FALSE
2867  * using this function, GTK+ will do its best to convince the window
2868  * manager not to decorate the window. Depending on the system, this
2869  * function may not have any effect when called on a window that is
2870  * already visible, so you should call it before calling gtk_window_show().
2871  *
2872  * On Windows, this function always works, since there's no window manager
2873  * policy involved.
2874  * 
2875  **/
2876 void
2877 gtk_window_set_decorated (GtkWindow *window,
2878                           gboolean   setting)
2879 {
2880   g_return_if_fail (GTK_IS_WINDOW (window));
2881
2882   setting = setting != FALSE;
2883
2884   if (setting == window->decorated)
2885     return;
2886
2887   window->decorated = setting;
2888   
2889   if (GTK_WIDGET (window)->window)
2890     {
2891       if (window->decorated)
2892         gdk_window_set_decorations (GTK_WIDGET (window)->window,
2893                                     GDK_DECOR_ALL);
2894       else
2895         gdk_window_set_decorations (GTK_WIDGET (window)->window,
2896                                     0);
2897     }
2898
2899   g_object_notify (G_OBJECT (window), "decorated");
2900 }
2901
2902 /**
2903  * gtk_window_get_decorated:
2904  * @window: a #GtkWindow
2905  *
2906  * Returns whether the window has been set to have decorations
2907  * such as a title bar via gtk_window_set_decorated().
2908  *
2909  * Return value: %TRUE if the window has been set to have decorations
2910  **/
2911 gboolean
2912 gtk_window_get_decorated (GtkWindow *window)
2913 {
2914   g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
2915
2916   return window->decorated;
2917 }
2918
2919 /**
2920  * gtk_window_set_deletable:
2921  * @window: a #GtkWindow
2922  * @setting: %TRUE to decorate the window as deletable
2923  *
2924  * By default, windows have a close button in the window frame. Some 
2925  * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to 
2926  * disable this button. If you set the deletable property to %FALSE
2927  * using this function, GTK+ will do its best to convince the window
2928  * manager not to show a close button. Depending on the system, this
2929  * function may not have any effect when called on a window that is
2930  * already visible, so you should call it before calling gtk_window_show().
2931  *
2932  * On Windows, this function always works, since there's no window manager
2933  * policy involved.
2934  *
2935  * Since: 2.10
2936  */
2937 void
2938 gtk_window_set_deletable (GtkWindow *window,
2939                           gboolean   setting)
2940 {
2941   GtkWindowPrivate *priv;
2942
2943   g_return_if_fail (GTK_IS_WINDOW (window));
2944
2945   priv = GTK_WINDOW_GET_PRIVATE (window);
2946
2947   setting = setting != FALSE;
2948
2949   if (setting == priv->deletable)
2950     return;
2951
2952   priv->deletable = setting;
2953   
2954   if (GTK_WIDGET (window)->window)
2955     {
2956       if (priv->deletable)
2957         gdk_window_set_functions (GTK_WIDGET (window)->window,
2958                                   GDK_FUNC_ALL);
2959       else
2960         gdk_window_set_functions (GTK_WIDGET (window)->window,
2961                                   GDK_FUNC_ALL | GDK_FUNC_CLOSE);
2962     }
2963
2964   g_object_notify (G_OBJECT (window), "deletable");  
2965 }
2966
2967 /**
2968  * gtk_window_get_deletable:
2969  * @window: a #GtkWindow
2970  *
2971  * Returns whether the window has been set to have a close button
2972  * via gtk_window_set_deletable().
2973  *
2974  * Return value: %TRUE if the window has been set to have a close button
2975  *
2976  * Since: 2.10
2977  **/
2978 gboolean
2979 gtk_window_get_deletable (GtkWindow *window)
2980 {
2981   GtkWindowPrivate *priv;
2982
2983   g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
2984
2985   priv = GTK_WINDOW_GET_PRIVATE (window);
2986
2987   return priv->deletable;
2988 }
2989
2990 static GtkWindowIconInfo*
2991 get_icon_info (GtkWindow *window)
2992 {
2993   return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
2994 }
2995      
2996 static void
2997 free_icon_info (GtkWindowIconInfo *info)
2998 {
2999   g_free (info->icon_name);
3000   g_slice_free (GtkWindowIconInfo, info);
3001 }
3002
3003
3004 static GtkWindowIconInfo*
3005 ensure_icon_info (GtkWindow *window)
3006 {
3007   GtkWindowIconInfo *info;
3008
3009   info = get_icon_info (window);
3010   
3011   if (info == NULL)
3012     {
3013       info = g_slice_new0 (GtkWindowIconInfo);
3014       g_object_set_qdata_full (G_OBJECT (window),
3015                               quark_gtk_window_icon_info,
3016                               info,
3017                               (GDestroyNotify)free_icon_info);
3018     }
3019
3020   return info;
3021 }
3022
3023 typedef struct {
3024   guint serial;
3025   GdkPixmap *pixmap;
3026   GdkPixmap *mask;
3027 } ScreenIconInfo;
3028
3029 static ScreenIconInfo *
3030 get_screen_icon_info (GdkScreen *screen)
3031 {
3032   ScreenIconInfo *info = g_object_get_qdata (G_OBJECT (screen), 
3033                                              quark_gtk_window_default_icon_pixmap);
3034   if (!info)
3035     {
3036       info = g_slice_new0 (ScreenIconInfo);
3037       g_object_set_qdata (G_OBJECT (screen), 
3038                           quark_gtk_window_default_icon_pixmap, info);
3039     }
3040
3041   if (info->serial != default_icon_serial)
3042     {
3043       if (info->pixmap)
3044         {
3045           g_object_remove_weak_pointer (G_OBJECT (info->pixmap), (gpointer*)&info->pixmap);
3046           info->pixmap = NULL;
3047         }
3048           
3049       if (info->mask)
3050         {
3051           g_object_remove_weak_pointer (G_OBJECT (info->mask), (gpointer*)&info->mask);
3052           info->mask = NULL;
3053         }
3054
3055       info->serial = default_icon_serial;
3056     }
3057   
3058   return info;
3059 }
3060
3061 static void
3062 get_pixmap_and_mask (GdkWindow          *window,
3063                      GtkWindowIconInfo  *parent_info,
3064                      gboolean            is_default_list,
3065                      GList              *icon_list,
3066                      GdkPixmap         **pmap_return,
3067                      GdkBitmap         **mask_return)
3068 {
3069   GdkScreen *screen = gdk_drawable_get_screen (window);
3070   ScreenIconInfo *default_icon_info = get_screen_icon_info (screen);
3071   GdkPixbuf *best_icon;
3072   GList *tmp_list;
3073   int best_size;
3074   
3075   *pmap_return = NULL;
3076   *mask_return = NULL;
3077   
3078   if (is_default_list &&
3079       default_icon_info->pixmap != NULL)
3080     {
3081       /* Use shared icon pixmap for all windows on this screen.
3082        */
3083       if (default_icon_info->pixmap)
3084         g_object_ref (default_icon_info->pixmap);
3085       if (default_icon_info->mask)
3086         g_object_ref (default_icon_info->mask);
3087
3088       *pmap_return = default_icon_info->pixmap;
3089       *mask_return = default_icon_info->mask;
3090     }
3091   else if (parent_info && parent_info->icon_pixmap)
3092     {
3093       if (parent_info->icon_pixmap)
3094         g_object_ref (parent_info->icon_pixmap);
3095       if (parent_info->icon_mask)
3096         g_object_ref (parent_info->icon_mask);
3097       
3098       *pmap_return = parent_info->icon_pixmap;
3099       *mask_return = parent_info->icon_mask;
3100     }
3101   else
3102     {
3103 #define IDEAL_SIZE 48
3104   
3105       best_size = G_MAXINT;
3106       best_icon = NULL;
3107       tmp_list = icon_list;
3108       while (tmp_list != NULL)
3109         {
3110           GdkPixbuf *pixbuf = tmp_list->data;
3111           int this;
3112       
3113           /* average width and height - if someone passes in a rectangular
3114            * icon they deserve what they get.
3115            */
3116           this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
3117           this /= 2;
3118       
3119           if (best_icon == NULL)
3120             {
3121               best_icon = pixbuf;
3122               best_size = this;
3123             }
3124           else
3125             {
3126               /* icon is better if it's 32 pixels or larger, and closer to
3127                * the ideal size than the current best.
3128                */
3129               if (this >= 32 &&
3130                   (ABS (best_size - IDEAL_SIZE) <
3131                    ABS (this - IDEAL_SIZE)))
3132                 {
3133                   best_icon = pixbuf;
3134                   best_size = this;
3135                 }
3136             }
3137
3138           tmp_list = tmp_list->next;
3139         }
3140
3141       if (best_icon)
3142         gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
3143                                                         gdk_screen_get_system_colormap (screen),
3144                                                         pmap_return,
3145                                                         mask_return,
3146                                                         128);
3147
3148       /* Save pmap/mask for others to use if appropriate */
3149       if (parent_info)
3150         {
3151           parent_info->icon_pixmap = *pmap_return;
3152           parent_info->icon_mask = *mask_return;
3153
3154           if (parent_info->icon_pixmap)
3155             g_object_ref (parent_info->icon_pixmap);
3156           if (parent_info->icon_mask)
3157             g_object_ref (parent_info->icon_mask);
3158         }
3159       else if (is_default_list)
3160         {
3161           default_icon_info->pixmap = *pmap_return;
3162           default_icon_info->mask = *mask_return;
3163
3164           if (default_icon_info->pixmap)
3165             g_object_add_weak_pointer (G_OBJECT (default_icon_info->pixmap),
3166                                        (gpointer*)&default_icon_info->pixmap);
3167           if (default_icon_info->mask) 
3168             g_object_add_weak_pointer (G_OBJECT (default_icon_info->mask),
3169                                        (gpointer*)&default_icon_info->mask);
3170         }
3171     }
3172 }
3173
3174 static GList *
3175 icon_list_from_theme (GtkWidget    *widget,
3176                       const gchar  *name)
3177 {
3178   GList *list;
3179
3180   GtkIconTheme *icon_theme;
3181   GdkPixbuf *icon;
3182   gint *sizes;
3183   gint i;
3184
3185   icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3186
3187   sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3188
3189   list = NULL;
3190   for (i = 0; sizes[i]; i++)
3191     {      
3192       /* FIXME
3193        * We need an EWMH extension to handle scalable icons 
3194        * by passing their name to the WM. For now just use a 
3195        * fixed size of 48.
3196        */ 
3197       if (sizes[i] == -1)
3198         icon = gtk_icon_theme_load_icon (icon_theme, name,
3199                                          48, 0, NULL);
3200       else
3201         icon = gtk_icon_theme_load_icon (icon_theme, name,
3202                                          sizes[i], 0, NULL);
3203       if (icon)
3204         list = g_list_append (list, icon);
3205     }
3206
3207   g_free (sizes);
3208
3209   return list;
3210 }
3211
3212
3213 static void
3214 gtk_window_realize_icon (GtkWindow *window)
3215 {
3216   GtkWidget *widget;
3217   GtkWindowIconInfo *info;
3218   GList *icon_list;
3219
3220   widget = GTK_WIDGET (window);
3221
3222   g_return_if_fail (widget->window != NULL);
3223
3224   /* no point setting an icon on override-redirect */
3225   if (window->type == GTK_WINDOW_POPUP)
3226     return;
3227
3228   icon_list = NULL;
3229   
3230   info = ensure_icon_info (window);
3231
3232   if (info->realized)
3233     return;
3234
3235   g_return_if_fail (info->icon_pixmap == NULL);
3236   g_return_if_fail (info->icon_mask == NULL);
3237   
3238   info->using_default_icon = FALSE;
3239   info->using_parent_icon = FALSE;
3240   info->using_themed_icon = FALSE;
3241   
3242   icon_list = info->icon_list;
3243
3244   /* Look up themed icon */
3245   if (icon_list == NULL && info->icon_name) 
3246     {
3247       icon_list = icon_list_from_theme (widget, info->icon_name);
3248       if (icon_list)
3249         info->using_themed_icon = TRUE;
3250     }
3251
3252   /* Inherit from transient parent */
3253   if (icon_list == NULL && window->transient_parent)
3254     {
3255       icon_list = ensure_icon_info (window->transient_parent)->icon_list;
3256       if (icon_list)
3257         info->using_parent_icon = TRUE;
3258     }      
3259
3260   /* Inherit from default */
3261   if (icon_list == NULL)
3262     {
3263       icon_list = default_icon_list;
3264       if (icon_list)
3265         info->using_default_icon = TRUE;
3266     }
3267
3268   /* Look up themed icon */
3269   if (icon_list == NULL && default_icon_name) 
3270     {
3271       icon_list = icon_list_from_theme (widget, default_icon_name);
3272       info->using_default_icon = TRUE;
3273       info->using_themed_icon = TRUE;  
3274     }
3275   
3276   gdk_window_set_icon_list (widget->window, icon_list);
3277
3278   get_pixmap_and_mask (widget->window,
3279                        info->using_parent_icon ? ensure_icon_info (window->transient_parent) : NULL,
3280                        info->using_default_icon,
3281                        icon_list,
3282                        &info->icon_pixmap,
3283                        &info->icon_mask);
3284   
3285   /* This is a slight ICCCM violation since it's a color pixmap not
3286    * a bitmap, but everyone does it.
3287    */
3288   gdk_window_set_icon (widget->window,
3289                        NULL,
3290                        info->icon_pixmap,
3291                        info->icon_mask);
3292
3293   info->realized = TRUE;
3294   
3295   if (info->using_themed_icon) 
3296     {
3297       GtkIconTheme *icon_theme;
3298
3299       g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
3300       g_list_free (icon_list);
3301  
3302       icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3303       g_signal_connect (icon_theme, "changed",
3304                         G_CALLBACK (update_themed_icon), window);
3305     }
3306 }
3307
3308 static void
3309 gtk_window_unrealize_icon (GtkWindow *window)
3310 {
3311   GtkWindowIconInfo *info;
3312
3313   info = get_icon_info (window);
3314
3315   if (info == NULL)
3316     return;
3317   
3318   if (info->icon_pixmap)
3319     g_object_unref (info->icon_pixmap);
3320
3321   if (info->icon_mask)
3322     g_object_unref (info->icon_mask);
3323
3324   info->icon_pixmap = NULL;
3325   info->icon_mask = NULL;
3326
3327   if (info->using_themed_icon)
3328     {
3329       GtkIconTheme *icon_theme;
3330
3331       icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3332
3333       g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3334     }
3335     
3336   /* We don't clear the properties on the window, just figure the
3337    * window is going away.
3338    */
3339
3340   info->realized = FALSE;
3341
3342 }
3343
3344 /**
3345  * gtk_window_set_icon_list:
3346  * @window: a #GtkWindow
3347  * @list: list of #GdkPixbuf
3348  *
3349  * Sets up the icon representing a #GtkWindow. The icon is used when
3350  * the window is minimized (also known as iconified).  Some window
3351  * managers or desktop environments may also place it in the window
3352  * frame, or display it in other contexts.
3353  *
3354  * gtk_window_set_icon_list() allows you to pass in the same icon in
3355  * several hand-drawn sizes. The list should contain the natural sizes
3356  * your icon is available in; that is, don't scale the image before
3357  * passing it to GTK+. Scaling is postponed until the last minute,
3358  * when the desired final size is known, to allow best quality.
3359  *
3360  * By passing several sizes, you may improve the final image quality
3361  * of the icon, by reducing or eliminating automatic image scaling.
3362  *
3363  * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3364  * larger images (64x64, 128x128) if you have them.
3365  *
3366  * See also gtk_window_set_default_icon_list() to set the icon
3367  * for all windows in your application in one go.
3368  *
3369  * Note that transient windows (those who have been set transient for another
3370  * window using gtk_window_set_transient_for()) will inherit their
3371  * icon from their transient parent. So there's no need to explicitly
3372  * set the icon on transient windows.
3373  **/
3374 void
3375 gtk_window_set_icon_list (GtkWindow  *window,
3376                           GList      *list)
3377 {
3378   GtkWindowIconInfo *info;
3379
3380   g_return_if_fail (GTK_IS_WINDOW (window));
3381
3382   info = ensure_icon_info (window);
3383
3384   if (info->icon_list == list) /* check for NULL mostly */
3385     return;
3386
3387   g_list_foreach (list,
3388                   (GFunc) g_object_ref, NULL);
3389
3390   g_list_foreach (info->icon_list,
3391                   (GFunc) g_object_unref, NULL);
3392
3393   g_list_free (info->icon_list);
3394
3395   info->icon_list = g_list_copy (list);
3396
3397   g_object_notify (G_OBJECT (window), "icon");
3398   
3399   gtk_window_unrealize_icon (window);
3400   
3401   if (GTK_WIDGET_REALIZED (window))
3402     gtk_window_realize_icon (window);
3403
3404   /* We could try to update our transient children, but I don't think
3405    * it's really worth it. If we did it, the best way would probably
3406    * be to have children connect to notify::icon-list
3407    */
3408 }
3409
3410 /**
3411  * gtk_window_get_icon_list:
3412  * @window: a #GtkWindow
3413  * 
3414  * Retrieves the list of icons set by gtk_window_set_icon_list().
3415  * The list is copied, but the reference count on each
3416  * member won't be incremented.
3417  * 
3418  * Return value: copy of window's icon list
3419  **/
3420 GList*
3421 gtk_window_get_icon_list (GtkWindow  *window)
3422 {
3423   GtkWindowIconInfo *info;
3424   
3425   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3426
3427   info = get_icon_info (window);
3428
3429   if (info)
3430     return g_list_copy (info->icon_list);
3431   else
3432     return NULL;  
3433 }
3434
3435 /**
3436  * gtk_window_set_icon:
3437  * @window: a #GtkWindow
3438  * @icon: icon image, or %NULL
3439  * 
3440  * Sets up the icon representing a #GtkWindow. This icon is used when
3441  * the window is minimized (also known as iconified).  Some window
3442  * managers or desktop environments may also place it in the window
3443  * frame, or display it in other contexts.
3444  *
3445  * The icon should be provided in whatever size it was naturally
3446  * drawn; that is, don't scale the image before passing it to
3447  * GTK+. Scaling is postponed until the last minute, when the desired
3448  * final size is known, to allow best quality.
3449  *
3450  * If you have your icon hand-drawn in multiple sizes, use
3451  * gtk_window_set_icon_list(). Then the best size will be used.
3452  *
3453  * This function is equivalent to calling gtk_window_set_icon_list()
3454  * with a 1-element list.
3455  *
3456  * See also gtk_window_set_default_icon_list() to set the icon
3457  * for all windows in your application in one go.
3458  **/
3459 void
3460 gtk_window_set_icon (GtkWindow  *window,
3461                      GdkPixbuf  *icon)
3462 {
3463   GList *list;
3464   
3465   g_return_if_fail (GTK_IS_WINDOW (window));
3466   g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3467
3468   list = NULL;
3469
3470   if (icon)
3471     list = g_list_append (list, icon);
3472   
3473   gtk_window_set_icon_list (window, list);
3474   g_list_free (list);  
3475 }
3476
3477
3478 static void 
3479 update_themed_icon (GtkIconTheme *icon_theme,
3480                     GtkWindow    *window)
3481 {
3482   g_object_notify (G_OBJECT (window), "icon");
3483   
3484   gtk_window_unrealize_icon (window);
3485   
3486   if (GTK_WIDGET_REALIZED (window))
3487     gtk_window_realize_icon (window);  
3488 }
3489
3490 /**
3491  * gtk_window_set_icon_name:
3492  * @window: a #GtkWindow
3493  * @name: the name of the themed icon
3494  *
3495  * Sets the icon for the window from a named themed icon. See
3496  * the docs for #GtkIconTheme for more details. 
3497  * 
3498  * Note that this has nothing to do with the WM_ICON_NAME 
3499  * property which is mentioned in the ICCCM.
3500  *
3501  * Since: 2.6
3502  */
3503 void 
3504 gtk_window_set_icon_name (GtkWindow   *window,
3505                           const gchar *name)
3506 {
3507   GtkWindowIconInfo *info;
3508   gchar *tmp;
3509   
3510   g_return_if_fail (GTK_IS_WINDOW (window));
3511
3512   info = ensure_icon_info (window);
3513
3514   if (g_strcmp0 (info->icon_name, name) == 0)
3515     return;
3516
3517   tmp = info->icon_name;
3518   info->icon_name = g_strdup (name);
3519   g_free (tmp);
3520
3521   g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3522   g_list_free (info->icon_list);
3523   info->icon_list = NULL;
3524   
3525   update_themed_icon (NULL, window);
3526
3527   g_object_notify (G_OBJECT (window), "icon-name");
3528 }
3529
3530 /**
3531  * gtk_window_get_icon_name:
3532  * @window: a #GtkWindow
3533  *
3534  * Returns the name of the themed icon for the window,
3535  * see gtk_window_set_icon_name().
3536  *
3537  * Returns: the icon name or %NULL if the window has 
3538  * no themed icon
3539  *
3540  * Since: 2.6
3541  */
3542 G_CONST_RETURN gchar *
3543 gtk_window_get_icon_name (GtkWindow *window)
3544 {
3545   GtkWindowIconInfo *info;
3546
3547   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3548
3549   info = ensure_icon_info (window);
3550
3551   return info->icon_name;
3552 }
3553
3554 /**
3555  * gtk_window_get_icon:
3556  * @window: a #GtkWindow
3557  * 
3558  * Gets the value set by gtk_window_set_icon() (or if you've
3559  * called gtk_window_set_icon_list(), gets the first icon in
3560  * the icon list).
3561  * 
3562  * Return value: icon for window
3563  **/
3564 GdkPixbuf*
3565 gtk_window_get_icon (GtkWindow  *window)
3566 {
3567   GtkWindowIconInfo *info;
3568
3569   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3570
3571   info = get_icon_info (window);
3572   if (info && info->icon_list)
3573     return GDK_PIXBUF (info->icon_list->data);
3574   else
3575     return NULL;
3576 }
3577
3578 /* Load pixbuf, printing warning on failure if error == NULL
3579  */
3580 static GdkPixbuf *
3581 load_pixbuf_verbosely (const char *filename,
3582                        GError    **err)
3583 {
3584   GError *local_err = NULL;
3585   GdkPixbuf *pixbuf;
3586
3587   pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3588
3589   if (!pixbuf)
3590     {
3591       if (err)
3592         *err = local_err;
3593       else
3594         {
3595           g_warning ("Error loading icon from file '%s':\n\t%s",
3596                      filename, local_err->message);
3597           g_error_free (local_err);
3598         }
3599     }
3600
3601   return pixbuf;
3602 }
3603
3604 /**
3605  * gtk_window_set_icon_from_file:
3606  * @window: a #GtkWindow
3607  * @filename: location of icon file
3608  * @err: location to store error, or %NULL.
3609  *
3610  * Sets the icon for @window.  
3611  * Warns on failure if @err is %NULL.
3612  *
3613  * This function is equivalent to calling gtk_window_set_icon()
3614  * with a pixbuf created by loading the image from @filename.
3615  *
3616  * Returns: %TRUE if setting the icon succeeded.
3617  *
3618  * Since: 2.2
3619  **/
3620 gboolean
3621 gtk_window_set_icon_from_file (GtkWindow   *window,
3622                                const gchar *filename,
3623                                GError     **err)
3624 {
3625   GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3626
3627   if (pixbuf)
3628     {
3629       gtk_window_set_icon (window, pixbuf);
3630       g_object_unref (pixbuf);
3631       
3632       return TRUE;
3633     }
3634   else
3635     return FALSE;
3636 }
3637
3638 /**
3639  * gtk_window_set_default_icon_list:
3640  * @list: a list of #GdkPixbuf
3641  *
3642  * Sets an icon list to be used as fallback for windows that haven't
3643  * had gtk_window_set_icon_list() called on them to set up a
3644  * window-specific icon list. This function allows you to set up the
3645  * icon for all windows in your app at once.
3646  *
3647  * See gtk_window_set_icon_list() for more details.
3648  * 
3649  **/
3650 void
3651 gtk_window_set_default_icon_list (GList *list)
3652 {
3653   GList *toplevels;
3654   GList *tmp_list;
3655   if (list == default_icon_list)
3656     return;
3657
3658   /* Update serial so we don't used cached pixmaps/masks
3659    */
3660   default_icon_serial++;
3661   
3662   g_list_foreach (list,
3663                   (GFunc) g_object_ref, NULL);
3664
3665   g_list_foreach (default_icon_list,
3666                   (GFunc) g_object_unref, NULL);
3667
3668   g_list_free (default_icon_list);
3669
3670   default_icon_list = g_list_copy (list);
3671   
3672   /* Update all toplevels */
3673   toplevels = gtk_window_list_toplevels ();
3674   tmp_list = toplevels;
3675   while (tmp_list != NULL)
3676     {
3677       GtkWindowIconInfo *info;
3678       GtkWindow *w = tmp_list->data;
3679       
3680       info = get_icon_info (w);
3681       if (info && info->using_default_icon)
3682         {
3683           gtk_window_unrealize_icon (w);
3684           if (GTK_WIDGET_REALIZED (w))
3685             gtk_window_realize_icon (w);
3686         }
3687
3688       tmp_list = tmp_list->next;
3689     }
3690   g_list_free (toplevels);
3691 }
3692
3693 /**
3694  * gtk_window_set_default_icon:
3695  * @icon: the icon
3696  *
3697  * Sets an icon to be used as fallback for windows that haven't
3698  * had gtk_window_set_icon() called on them from a pixbuf.
3699  *
3700  * Since: 2.4
3701  **/
3702 void
3703 gtk_window_set_default_icon (GdkPixbuf *icon)
3704 {
3705   GList *list;
3706   
3707   g_return_if_fail (GDK_IS_PIXBUF (icon));
3708
3709   list = g_list_prepend (NULL, icon);
3710   gtk_window_set_default_icon_list (list);
3711   g_list_free (list);
3712 }
3713
3714 /**
3715  * gtk_window_set_default_icon_name:
3716  * @name: the name of the themed icon
3717  *
3718  * Sets an icon to be used as fallback for windows that haven't
3719  * had gtk_window_set_icon_list() called on them from a named
3720  * themed icon, see gtk_window_set_icon_name().
3721  *
3722  * Since: 2.6
3723  **/
3724 void
3725 gtk_window_set_default_icon_name (const gchar *name)
3726 {
3727   GList *tmp_list;
3728   GList *toplevels;
3729
3730   /* Update serial so we don't used cached pixmaps/masks
3731    */
3732   default_icon_serial++;
3733
3734   g_free (default_icon_name);
3735   default_icon_name = g_strdup (name);
3736
3737   g_list_foreach (default_icon_list,
3738                   (GFunc) g_object_unref, NULL);
3739
3740   g_list_free (default_icon_list);
3741   default_icon_list = NULL;
3742   
3743   /* Update all toplevels */
3744   toplevels = gtk_window_list_toplevels ();
3745   tmp_list = toplevels;
3746   while (tmp_list != NULL)
3747     {
3748       GtkWindowIconInfo *info;
3749       GtkWindow *w = tmp_list->data;
3750       
3751       info = get_icon_info (w);
3752       if (info && info->using_default_icon && info->using_themed_icon)
3753         {
3754           gtk_window_unrealize_icon (w);
3755           if (GTK_WIDGET_REALIZED (w))
3756             gtk_window_realize_icon (w);
3757         }
3758
3759       tmp_list = tmp_list->next;
3760     }
3761   g_list_free (toplevels);
3762 }
3763
3764 /**
3765  * gtk_window_get_default_icon_name:
3766  *
3767  * Returns the fallback icon name for windows that has been set
3768  * with gtk_window_set_default_icon_name(). The returned
3769  * string is owned by GTK+ and should not be modified. It
3770  * is only valid until the next call to
3771  * gtk_window_set_default_icon_name().
3772  *
3773  * Returns: the fallback icon name for windows
3774  *
3775  * Since: 2.16
3776  */
3777 const gchar *
3778 gtk_window_get_default_icon_name (void)
3779 {
3780   return default_icon_name;
3781 }
3782
3783 /**
3784  * gtk_window_set_default_icon_from_file:
3785  * @filename: location of icon file
3786  * @err: location to store error, or %NULL.
3787  *
3788  * Sets an icon to be used as fallback for windows that haven't
3789  * had gtk_window_set_icon_list() called on them from a file
3790  * on disk. Warns on failure if @err is %NULL.
3791  *
3792  * Returns: %TRUE if setting the icon succeeded.
3793  *
3794  * Since: 2.2
3795  **/
3796 gboolean
3797 gtk_window_set_default_icon_from_file (const gchar *filename,
3798                                        GError     **err)
3799 {
3800   GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3801
3802   if (pixbuf)
3803     {
3804       gtk_window_set_default_icon (pixbuf);
3805       g_object_unref (pixbuf);
3806       
3807       return TRUE;
3808     }
3809   else
3810     return FALSE;
3811 }
3812
3813 /**
3814  * gtk_window_get_default_icon_list:
3815  * 
3816  * Gets the value set by gtk_window_set_default_icon_list().
3817  * The list is a copy and should be freed with g_list_free(),
3818  * but the pixbufs in the list have not had their reference count
3819  * incremented.
3820  * 
3821  * Return value: copy of default icon list 
3822  **/
3823 GList*
3824 gtk_window_get_default_icon_list (void)
3825 {
3826   return g_list_copy (default_icon_list);
3827 }
3828
3829 static void
3830 gtk_window_set_default_size_internal (GtkWindow    *window,
3831                                       gboolean      change_width,
3832                                       gint          width,
3833                                       gboolean      change_height,
3834                                       gint          height,
3835                                       gboolean      is_geometry)
3836 {
3837   GtkWindowGeometryInfo *info;
3838
3839   g_return_if_fail (change_width == FALSE || width >= -1);
3840   g_return_if_fail (change_height == FALSE || height >= -1);
3841
3842   info = gtk_window_get_geometry_info (window, TRUE);
3843
3844   g_object_freeze_notify (G_OBJECT (window));
3845
3846   info->default_is_geometry = is_geometry != FALSE;
3847
3848   if (change_width)
3849     {
3850       if (width == 0)
3851         width = 1;
3852
3853       if (width < 0)
3854         width = -1;
3855
3856       info->default_width = width;
3857
3858       g_object_notify (G_OBJECT (window), "default-width");
3859     }
3860
3861   if (change_height)
3862     {
3863       if (height == 0)
3864         height = 1;
3865
3866       if (height < 0)
3867         height = -1;
3868
3869       info->default_height = height;
3870       
3871       g_object_notify (G_OBJECT (window), "default-height");
3872     }
3873   
3874   g_object_thaw_notify (G_OBJECT (window));
3875   
3876   gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3877 }
3878
3879 /**
3880  * gtk_window_set_default_size:
3881  * @window: a #GtkWindow
3882  * @width: width in pixels, or -1 to unset the default width
3883  * @height: height in pixels, or -1 to unset the default height
3884  *
3885  * Sets the default size of a window. If the window's "natural" size
3886  * (its size request) is larger than the default, the default will be
3887  * ignored. More generally, if the default size does not obey the
3888  * geometry hints for the window (gtk_window_set_geometry_hints() can
3889  * be used to set these explicitly), the default size will be clamped
3890  * to the nearest permitted size.
3891  * 
3892  * Unlike gtk_widget_set_size_request(), which sets a size request for
3893  * a widget and thus would keep users from shrinking the window, this
3894  * function only sets the initial size, just as if the user had
3895  * resized the window themselves. Users can still shrink the window
3896  * again as they normally would. Setting a default size of -1 means to
3897  * use the "natural" default size (the size request of the window).
3898  *
3899  * For more control over a window's initial size and how resizing works,
3900  * investigate gtk_window_set_geometry_hints().
3901  *
3902  * For some uses, gtk_window_resize() is a more appropriate function.
3903  * gtk_window_resize() changes the current size of the window, rather
3904  * than the size to be used on initial display. gtk_window_resize() always
3905  * affects the window itself, not the geometry widget.
3906  *
3907  * The default size of a window only affects the first time a window is
3908  * shown; if a window is hidden and re-shown, it will remember the size
3909  * it had prior to hiding, rather than using the default size.
3910  *
3911  * Windows can't actually be 0x0 in size, they must be at least 1x1, but
3912  * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
3913  **/
3914 void       
3915 gtk_window_set_default_size (GtkWindow   *window,
3916                              gint         width,
3917                              gint         height)
3918 {
3919   g_return_if_fail (GTK_IS_WINDOW (window));
3920   g_return_if_fail (width >= -1);
3921   g_return_if_fail (height >= -1);
3922
3923   gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
3924 }
3925
3926 /**
3927  * gtk_window_get_default_size:
3928  * @window: a #GtkWindow
3929  * @width: location to store the default width, or %NULL
3930  * @height: location to store the default height, or %NULL
3931  *
3932  * Gets the default size of the window. A value of -1 for the width or
3933  * height indicates that a default size has not been explicitly set
3934  * for that dimension, so the "natural" size of the window will be
3935  * used.
3936  * 
3937  **/
3938 void
3939 gtk_window_get_default_size (GtkWindow *window,
3940                              gint      *width,
3941                              gint      *height)
3942 {
3943   GtkWindowGeometryInfo *info;
3944
3945   g_return_if_fail (GTK_IS_WINDOW (window));
3946
3947   info = gtk_window_get_geometry_info (window, FALSE);
3948
3949   if (width)
3950     *width = info ? info->default_width : -1;
3951
3952   if (height)
3953     *height = info ? info->default_height : -1;
3954 }
3955
3956 /**
3957  * gtk_window_resize:
3958  * @window: a #GtkWindow
3959  * @width: width in pixels to resize the window to
3960  * @height: height in pixels to resize the window to
3961  *
3962  * Resizes the window as if the user had done so, obeying geometry
3963  * constraints. The default geometry constraint is that windows may
3964  * not be smaller than their size request; to override this
3965  * constraint, call gtk_widget_set_size_request() to set the window's
3966  * request to a smaller value.
3967  *
3968  * If gtk_window_resize() is called before showing a window for the
3969  * first time, it overrides any default size set with
3970  * gtk_window_set_default_size().
3971  *
3972  * Windows may not be resized smaller than 1 by 1 pixels.
3973  * 
3974  **/
3975 void
3976 gtk_window_resize (GtkWindow *window,
3977                    gint       width,
3978                    gint       height)
3979 {
3980   GtkWindowGeometryInfo *info;
3981   
3982   g_return_if_fail (GTK_IS_WINDOW (window));
3983   g_return_if_fail (width > 0);
3984   g_return_if_fail (height > 0);
3985
3986   info = gtk_window_get_geometry_info (window, TRUE);
3987
3988   info->resize_width = width;
3989   info->resize_height = height;
3990
3991   gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3992 }
3993
3994 /**
3995  * gtk_window_get_size:
3996  * @window: a #GtkWindow
3997  * @width: return location for width, or %NULL
3998  * @height: return location for height, or %NULL
3999  *
4000  * Obtains the current size of @window. If @window is not onscreen,
4001  * it returns the size GTK+ will suggest to the <link
4002  * linkend="gtk-X11-arch">window manager</link> for the initial window
4003  * size (but this is not reliably the same as the size the window
4004  * manager will actually select). The size obtained by
4005  * gtk_window_get_size() is the last size received in a
4006  * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4007  * rather than querying the X server for the size. As a result, if you
4008  * call gtk_window_resize() then immediately call
4009  * gtk_window_get_size(), the size won't have taken effect yet. After
4010  * the window manager processes the resize request, GTK+ receives
4011  * notification that the size has changed via a configure event, and
4012  * the size of the window gets updated.
4013  *
4014  * Note 1: Nearly any use of this function creates a race condition,
4015  * because the size of the window may change between the time that you
4016  * get the size and the time that you perform some action assuming
4017  * that size is the current size. To avoid race conditions, connect to
4018  * "configure-event" on the window and adjust your size-dependent
4019  * state to match the size delivered in the #GdkEventConfigure.
4020  *
4021  * Note 2: The returned size does <emphasis>not</emphasis> include the
4022  * size of the window manager decorations (aka the window frame or
4023  * border). Those are not drawn by GTK+ and GTK+ has no reliable
4024  * method of determining their size.
4025  *
4026  * Note 3: If you are getting a window size in order to position
4027  * the window onscreen, there may be a better way. The preferred
4028  * way is to simply set the window's semantic type with
4029  * gtk_window_set_type_hint(), which allows the window manager to
4030  * e.g. center dialogs. Also, if you set the transient parent of
4031  * dialogs with gtk_window_set_transient_for() window managers
4032  * will often center the dialog over its parent window. It's
4033  * much preferred to let the window manager handle these
4034  * things rather than doing it yourself, because all apps will
4035  * behave consistently and according to user prefs if the window
4036  * manager handles it. Also, the window manager can take the size
4037  * of the window decorations/border into account, while your
4038  * application cannot.
4039  *
4040  * In any case, if you insist on application-specified window
4041  * positioning, there's <emphasis>still</emphasis> a better way than
4042  * doing it yourself - gtk_window_set_position() will frequently
4043  * handle the details for you.
4044  * 
4045  **/
4046 void
4047 gtk_window_get_size (GtkWindow *window,
4048                      gint      *width,
4049                      gint      *height)
4050 {
4051   gint w, h;
4052   
4053   g_return_if_fail (GTK_IS_WINDOW (window));
4054
4055   if (width == NULL && height == NULL)
4056     return;
4057
4058   if (GTK_WIDGET_MAPPED (window))
4059     {
4060       gdk_drawable_get_size (GTK_WIDGET (window)->window,
4061                              &w, &h);
4062     }
4063   else
4064     {
4065       GdkRectangle configure_request;
4066
4067       gtk_window_compute_configure_request (window,
4068                                             &configure_request,
4069                                             NULL, NULL);
4070
4071       w = configure_request.width;
4072       h = configure_request.height;
4073     }
4074   
4075   if (width)
4076     *width = w;
4077   if (height)
4078     *height = h;
4079 }
4080
4081 /**
4082  * gtk_window_move:
4083  * @window: a #GtkWindow
4084  * @x: X coordinate to move window to
4085  * @y: Y coordinate to move window to
4086  *
4087  * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4088  * @window to the given position.  Window managers are free to ignore
4089  * this; most window managers ignore requests for initial window
4090  * positions (instead using a user-defined placement algorithm) and
4091  * honor requests after the window has already been shown.
4092  *
4093  * Note: the position is the position of the gravity-determined
4094  * reference point for the window. The gravity determines two things:
4095  * first, the location of the reference point in root window
4096  * coordinates; and second, which point on the window is positioned at
4097  * the reference point.
4098  *
4099  * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4100  * point is simply the @x, @y supplied to gtk_window_move(). The
4101  * top-left corner of the window decorations (aka window frame or
4102  * border) will be placed at @x, @y.  Therefore, to position a window
4103  * at the top left of the screen, you want to use the default gravity
4104  * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4105  *
4106  * To position a window at the bottom right corner of the screen, you
4107  * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4108  * point is at @x + the window width and @y + the window height, and
4109  * the bottom-right corner of the window border will be placed at that
4110  * reference point. So, to place a window in the bottom right corner
4111  * you would first set gravity to south east, then write:
4112  * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4113  * gdk_screen_height () - window_height)</literal> (note that this
4114  * example does not take multi-head scenarios into account).
4115  *
4116  * The Extended Window Manager Hints specification at <ulink 
4117  * url="http://www.freedesktop.org/Standards/wm-spec">
4118  * http://www.freedesktop.org/Standards/wm-spec</ulink> has a 
4119  * nice table of gravities in the "implementation notes" section.
4120  *
4121  * The gtk_window_get_position() documentation may also be relevant.
4122  */
4123 void
4124 gtk_window_move (GtkWindow *window,
4125                  gint       x,
4126                  gint       y)
4127 {
4128   GtkWindowGeometryInfo *info;
4129   GtkWidget *widget;
4130   
4131   g_return_if_fail (GTK_IS_WINDOW (window));
4132
4133   widget = GTK_WIDGET (window);
4134
4135   info = gtk_window_get_geometry_info (window, TRUE);  
4136   
4137   if (GTK_WIDGET_MAPPED (window))
4138     {
4139       /* we have now sent a request with this position
4140        * with currently-active constraints, so toggle flag.
4141        */
4142       info->position_constraints_changed = FALSE;
4143
4144       /* we only constrain if mapped - if not mapped,
4145        * then gtk_window_compute_configure_request()
4146        * will apply the constraints later, and we
4147        * don't want to lose information about
4148        * what position the user set before then.
4149        * i.e. if you do a move() then turn off POS_CENTER
4150        * then show the window, your move() will work.
4151        */
4152       gtk_window_constrain_position (window,
4153                                      widget->allocation.width,
4154                                      widget->allocation.height,
4155                                      &x, &y);
4156       
4157       /* Note that this request doesn't go through our standard request
4158        * framework, e.g. doesn't increment configure_request_count,
4159        * doesn't set info->last, etc.; that's because
4160        * we don't save the info needed to arrive at this same request
4161        * again.
4162        *
4163        * To gtk_window_move_resize(), this will end up looking exactly
4164        * the same as the position being changed by the window
4165        * manager.
4166        */
4167       
4168       /* FIXME are we handling gravity properly for framed windows? */
4169       if (window->frame)
4170         gdk_window_move (window->frame,
4171                          x - window->frame_left,
4172                          y - window->frame_top);
4173       else
4174         gdk_window_move (GTK_WIDGET (window)->window,
4175                          x, y);
4176     }
4177   else
4178     {
4179       /* Save this position to apply on mapping */
4180       info->initial_x = x;
4181       info->initial_y = y;
4182       info->initial_pos_set = TRUE;
4183     }
4184 }
4185
4186 /**
4187  * gtk_window_get_position:
4188  * @window: a #GtkWindow
4189  * @root_x: return location for X coordinate of gravity-determined reference point
4190  * @root_y: return location for Y coordinate of gravity-determined reference point
4191  *
4192  * This function returns the position you need to pass to
4193  * gtk_window_move() to keep @window in its current position.  This
4194  * means that the meaning of the returned value varies with window
4195  * gravity. See gtk_window_move() for more details.
4196  * 
4197  * If you haven't changed the window gravity, its gravity will be
4198  * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4199  * gets the position of the top-left corner of the window manager
4200  * frame for the window. gtk_window_move() sets the position of this
4201  * same top-left corner.
4202  *
4203  * gtk_window_get_position() is not 100% reliable because the X Window System
4204  * does not specify a way to obtain the geometry of the
4205  * decorations placed on a window by the window manager.
4206  * Thus GTK+ is using a "best guess" that works with most
4207  * window managers.
4208  *
4209  * Moreover, nearly all window managers are historically broken with
4210  * respect to their handling of window gravity. So moving a window to
4211  * its current position as returned by gtk_window_get_position() tends
4212  * to result in moving the window slightly. Window managers are
4213  * slowly getting better over time.
4214  *
4215  * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4216  * frame is not relevant, and thus gtk_window_get_position() will
4217  * always produce accurate results. However you can't use static
4218  * gravity to do things like place a window in a corner of the screen,
4219  * because static gravity ignores the window manager decorations.
4220  *
4221  * If you are saving and restoring your application's window
4222  * positions, you should know that it's impossible for applications to
4223  * do this without getting it somewhat wrong because applications do
4224  * not have sufficient knowledge of window manager state. The Correct
4225  * Mechanism is to support the session management protocol (see the
4226  * "GnomeClient" object in the GNOME libraries for example) and allow
4227  * the window manager to save your window sizes and positions.
4228  * 
4229  **/
4230
4231 void
4232 gtk_window_get_position (GtkWindow *window,
4233                          gint      *root_x,
4234                          gint      *root_y)
4235 {
4236   GtkWidget *widget;
4237
4238   g_return_if_fail (GTK_IS_WINDOW (window));
4239
4240   widget = GTK_WIDGET (window);
4241   
4242   if (window->gravity == GDK_GRAVITY_STATIC)
4243     {
4244       if (GTK_WIDGET_MAPPED (widget))
4245         {
4246           /* This does a server round-trip, which is sort of wrong;
4247            * but a server round-trip is inevitable for
4248            * gdk_window_get_frame_extents() in the usual
4249            * NorthWestGravity case below, so not sure what else to
4250            * do. We should likely be consistent about whether we get
4251            * the client-side info or the server-side info.
4252            */
4253           gdk_window_get_origin (widget->window, root_x, root_y);
4254         }
4255       else
4256         {
4257           GdkRectangle configure_request;
4258           
4259           gtk_window_compute_configure_request (window,
4260                                                 &configure_request,
4261                                                 NULL, NULL);
4262           
4263           *root_x = configure_request.x;
4264           *root_y = configure_request.y;
4265         }
4266     }
4267   else
4268     {
4269       GdkRectangle frame_extents;
4270       
4271       gint x, y;
4272       gint w, h;
4273       
4274       if (GTK_WIDGET_MAPPED (widget))
4275         {
4276           if (window->frame)
4277             gdk_window_get_frame_extents (window->frame, &frame_extents);
4278           else
4279             gdk_window_get_frame_extents (widget->window, &frame_extents);
4280           x = frame_extents.x;
4281           y = frame_extents.y;
4282           gtk_window_get_size (window, &w, &h);
4283         }
4284       else
4285         {
4286           /* We just say the frame has 0 size on all sides.
4287            * Not sure what else to do.
4288            */             
4289           gtk_window_compute_configure_request (window,
4290                                                 &frame_extents,
4291                                                 NULL, NULL);
4292           x = frame_extents.x;
4293           y = frame_extents.y;
4294           w = frame_extents.width;
4295           h = frame_extents.height;
4296         }
4297       
4298       switch (window->gravity)
4299         {
4300         case GDK_GRAVITY_NORTH:
4301         case GDK_GRAVITY_CENTER:
4302         case GDK_GRAVITY_SOUTH:
4303           /* Find center of frame. */
4304           x += frame_extents.width / 2;
4305           /* Center client window on that point. */
4306           x -= w / 2;
4307           break;
4308
4309         case GDK_GRAVITY_SOUTH_EAST:
4310         case GDK_GRAVITY_EAST:
4311         case GDK_GRAVITY_NORTH_EAST:
4312           /* Find right edge of frame */
4313           x += frame_extents.width;
4314           /* Align left edge of client at that point. */
4315           x -= w;
4316           break;
4317         default:
4318           break;
4319         }
4320
4321       switch (window->gravity)
4322         {
4323         case GDK_GRAVITY_WEST:
4324         case GDK_GRAVITY_CENTER:
4325         case GDK_GRAVITY_EAST:
4326           /* Find center of frame. */
4327           y += frame_extents.height / 2;
4328           /* Center client window there. */
4329           y -= h / 2;
4330           break;
4331         case GDK_GRAVITY_SOUTH_WEST:
4332         case GDK_GRAVITY_SOUTH:
4333         case GDK_GRAVITY_SOUTH_EAST:
4334           /* Find south edge of frame */
4335           y += frame_extents.height;
4336           /* Place bottom edge of client there */
4337           y -= h;
4338           break;
4339         default:
4340           break;
4341         }
4342       
4343       if (root_x)
4344         *root_x = x;
4345       if (root_y)
4346         *root_y = y;
4347     }
4348 }
4349
4350 /**
4351  * gtk_window_reshow_with_initial_size:
4352  * @window: a #GtkWindow
4353  * 
4354  * Hides @window, then reshows it, resetting the
4355  * default size and position of the window. Used
4356  * by GUI builders only.
4357  **/
4358 void
4359 gtk_window_reshow_with_initial_size (GtkWindow *window)
4360 {
4361   GtkWidget *widget;
4362   
4363   g_return_if_fail (GTK_IS_WINDOW (window));
4364
4365   widget = GTK_WIDGET (window);
4366   
4367   gtk_widget_hide (widget);
4368   gtk_widget_unrealize (widget);
4369   gtk_widget_show (widget);
4370 }
4371
4372 static void
4373 gtk_window_destroy (GtkObject *object)
4374 {
4375   GtkWindow *window = GTK_WINDOW (object);
4376   
4377   toplevel_list = g_slist_remove (toplevel_list, window);
4378
4379   if (window->transient_parent)
4380     gtk_window_set_transient_for (window, NULL);
4381
4382   /* frees the icons */
4383   gtk_window_set_icon_list (window, NULL);
4384   
4385   if (window->has_user_ref_count)
4386     {
4387       window->has_user_ref_count = FALSE;
4388       g_object_unref (window);
4389     }
4390
4391   if (window->group)
4392     gtk_window_group_remove_window (window->group, window);
4393
4394    gtk_window_free_key_hash (window);
4395
4396    GTK_OBJECT_CLASS (gtk_window_parent_class)->destroy (object);
4397 }
4398
4399 static void
4400 gtk_window_finalize (GObject *object)
4401 {
4402   GtkWindow *window = GTK_WINDOW (object);
4403   GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
4404   GtkMnemonicHash *mnemonic_hash;
4405
4406   g_free (window->title);
4407   g_free (window->wmclass_name);
4408   g_free (window->wmclass_class);
4409   g_free (window->wm_role);
4410
4411   mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4412   if (mnemonic_hash)
4413     _gtk_mnemonic_hash_free (mnemonic_hash);
4414
4415   if (window->geometry_info)
4416     {
4417       if (window->geometry_info->widget)
4418         g_signal_handlers_disconnect_by_func (window->geometry_info->widget,
4419                                               gtk_widget_destroyed,
4420                                               &window->geometry_info->widget);
4421       g_free (window->geometry_info);
4422     }
4423
4424   if (window->keys_changed_handler)
4425     {
4426       g_source_remove (window->keys_changed_handler);
4427       window->keys_changed_handler = 0;
4428     }
4429
4430   if (window->screen)
4431     g_signal_handlers_disconnect_by_func (window->screen,
4432                                           gtk_window_on_composited_changed, window);
4433
4434   g_free (priv->startup_id);
4435
4436   G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4437 }
4438
4439 static void
4440 gtk_window_show (GtkWidget *widget)
4441 {
4442   GtkWindow *window = GTK_WINDOW (widget);
4443   GtkContainer *container = GTK_CONTAINER (window);
4444   gboolean need_resize;
4445
4446   GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
4447   
4448   need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
4449   container->need_resize = FALSE;
4450
4451   if (need_resize)
4452     {
4453       GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4454       GtkAllocation allocation = { 0, 0 };
4455       GdkRectangle configure_request;
4456       GdkGeometry new_geometry;
4457       guint new_flags;
4458       gboolean was_realized;
4459
4460       /* We are going to go ahead and perform this configure request
4461        * and then emulate a configure notify by going ahead and
4462        * doing a size allocate. Sort of a synchronous
4463        * mini-copy of gtk_window_move_resize() here.
4464        */
4465       gtk_window_compute_configure_request (window,
4466                                             &configure_request,
4467                                             &new_geometry,
4468                                             &new_flags);
4469       
4470       /* We update this because we are going to go ahead
4471        * and gdk_window_resize() below, rather than
4472        * queuing it.
4473        */
4474       info->last.configure_request.width = configure_request.width;
4475       info->last.configure_request.height = configure_request.height;
4476       
4477       /* and allocate the window - this is normally done
4478        * in move_resize in response to configure notify
4479        */
4480       allocation.width  = configure_request.width;
4481       allocation.height = configure_request.height;
4482       gtk_widget_size_allocate (widget, &allocation);
4483
4484       /* Then we guarantee we have a realize */
4485       was_realized = FALSE;
4486       if (!GTK_WIDGET_REALIZED (widget))
4487         {
4488           gtk_widget_realize (widget);
4489           was_realized = TRUE;
4490         }
4491
4492       /* Must be done after the windows are realized,
4493        * so that the decorations can be read
4494        */
4495       gtk_decorated_window_calculate_frame_size (window);
4496
4497       /* We only send configure request if we didn't just finish
4498        * creating the window; if we just created the window
4499        * then we created it with widget->allocation anyhow.
4500        */
4501       if (!was_realized)
4502         gdk_window_move_resize (widget->window,
4503                                 configure_request.x,
4504                                 configure_request.y,
4505                                 configure_request.width,
4506                                 configure_request.height);
4507     }
4508   
4509   gtk_container_check_resize (container);
4510
4511   gtk_widget_map (widget);
4512
4513   /* Try to make sure that we have some focused widget
4514    */
4515   if (!window->focus_widget && !GTK_IS_PLUG (window))
4516     gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD);
4517   
4518   if (window->modal)
4519     gtk_grab_add (widget);
4520 }
4521
4522 static void
4523 gtk_window_hide (GtkWidget *widget)
4524 {
4525   GtkWindow *window = GTK_WINDOW (widget);
4526
4527   GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
4528   gtk_widget_unmap (widget);
4529
4530   if (window->modal)
4531     gtk_grab_remove (widget);
4532 }
4533
4534 static void
4535 gtk_window_map (GtkWidget *widget)
4536 {
4537   GtkWindow *window = GTK_WINDOW (widget);
4538   GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
4539   GdkWindow *toplevel;
4540
4541   GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
4542
4543   if (window->bin.child &&
4544       GTK_WIDGET_VISIBLE (window->bin.child) &&
4545       !GTK_WIDGET_MAPPED (window->bin.child))
4546     gtk_widget_map (window->bin.child);
4547
4548   if (window->frame)
4549     toplevel = window->frame;
4550   else
4551     toplevel = widget->window;
4552   
4553   if (window->maximize_initially)
4554     gdk_window_maximize (toplevel);
4555   else
4556     gdk_window_unmaximize (toplevel);
4557   
4558   if (window->stick_initially)
4559     gdk_window_stick (toplevel);
4560   else
4561     gdk_window_unstick (toplevel);
4562   
4563   if (window->iconify_initially)
4564     gdk_window_iconify (toplevel);
4565   else
4566     gdk_window_deiconify (toplevel);
4567
4568   if (priv->fullscreen_initially)
4569     gdk_window_fullscreen (toplevel);
4570   else
4571     gdk_window_unfullscreen (toplevel);
4572   
4573   gdk_window_set_keep_above (toplevel, priv->above_initially);
4574
4575   gdk_window_set_keep_below (toplevel, priv->below_initially);
4576
4577   /* No longer use the default settings */
4578   window->need_default_size = FALSE;
4579   window->need_default_position = FALSE;
4580   
4581   if (priv->reset_type_hint)
4582     {
4583       /* We should only reset the type hint when the application
4584        * used gtk_window_set_type_hint() to change the hint.
4585        * Some applications use X directly to change the properties;
4586        * in that case, we shouldn't overwrite what they did.
4587        */
4588       gdk_window_set_type_hint (widget->window, priv->type_hint);
4589       priv->reset_type_hint = FALSE;
4590     }
4591
4592   gdk_window_show (widget->window);
4593
4594   if (window->frame)
4595     gdk_window_show (window->frame);
4596
4597   if (!disable_startup_notification)
4598     {
4599       /* Do we have a custom startup-notification id? */
4600       if (priv->startup_id != NULL)
4601         {
4602           /* Make sure we have a "real" id */
4603           if (!startup_id_is_fake (priv->startup_id)) 
4604             gdk_notify_startup_complete_with_id (priv->startup_id);
4605
4606           g_free (priv->startup_id);
4607           priv->startup_id = NULL;
4608         }
4609       else if (!sent_startup_notification)
4610         {
4611           sent_startup_notification = TRUE;
4612           gdk_notify_startup_complete ();
4613         }
4614     }
4615 }
4616
4617 static gboolean
4618 gtk_window_map_event (GtkWidget   *widget,
4619                       GdkEventAny *event)
4620 {
4621   if (!GTK_WIDGET_MAPPED (widget))
4622     {
4623       /* we should be be unmapped, but are getting a MapEvent, this may happen
4624        * to toplevel XWindows if mapping was intercepted by a window manager
4625        * and an unmap request occoured while the MapRequestEvent was still
4626        * being handled. we work around this situaiton here by re-requesting
4627        * the window being unmapped. more details can be found in:
4628        *   http://bugzilla.gnome.org/show_bug.cgi?id=316180
4629        */
4630       gdk_window_hide (widget->window);
4631     }
4632   return FALSE;
4633 }
4634
4635 static void
4636 gtk_window_unmap (GtkWidget *widget)
4637 {
4638   GtkWindow *window = GTK_WINDOW (widget);
4639   GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (widget);
4640   GtkWindowGeometryInfo *info;    
4641   GdkWindowState state;
4642
4643   GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
4644   if (window->frame)
4645     gdk_window_withdraw (window->frame);
4646   else 
4647     gdk_window_withdraw (widget->window);
4648   
4649   window->configure_request_count = 0;
4650   window->configure_notify_received = FALSE;
4651
4652   /* on unmap, we reset the default positioning of the window,
4653    * so it's placed again, but we don't reset the default
4654    * size of the window, so it's remembered.
4655    */
4656   window->need_default_position = TRUE;
4657
4658   info = gtk_window_get_geometry_info (window, FALSE);
4659   if (info)
4660     {
4661       info->initial_pos_set = FALSE;
4662       info->position_constraints_changed = FALSE;
4663     }
4664
4665   state = gdk_window_get_state (widget->window);
4666   window->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4667   window->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4668   window->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4669   priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4670   priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4671 }
4672
4673 static void
4674 gtk_window_realize (GtkWidget *widget)
4675 {
4676   GtkWindow *window;
4677   GdkWindow *parent_window;
4678   GdkWindowAttr attributes;
4679   gint attributes_mask;
4680   GtkWindowPrivate *priv;
4681   
4682   window = GTK_WINDOW (widget);
4683   priv = GTK_WINDOW_GET_PRIVATE (window);
4684
4685   /* ensure widget tree is properly size allocated */
4686   if (widget->allocation.x == -1 &&
4687       widget->allocation.y == -1 &&
4688       widget->allocation.width == 1 &&
4689       widget->allocation.height == 1)
4690     {
4691       GtkRequisition requisition;
4692       GtkAllocation allocation = { 0, 0, 200, 200 };
4693
4694       gtk_widget_size_request (widget, &requisition);
4695       if (requisition.width || requisition.height)
4696         {
4697           /* non-empty window */
4698           allocation.width = requisition.width;
4699           allocation.height = requisition.height;
4700         }
4701       gtk_widget_size_allocate (widget, &allocation);
4702       
4703       _gtk_container_queue_resize (GTK_CONTAINER (widget));
4704
4705       g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
4706     }
4707   
4708   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
4709   
4710   switch (window->type)
4711     {
4712     case GTK_WINDOW_TOPLEVEL:
4713       attributes.window_type = GDK_WINDOW_TOPLEVEL;
4714       break;
4715     case GTK_WINDOW_POPUP:
4716       attributes.window_type = GDK_WINDOW_TEMP;
4717       break;
4718     default:
4719       g_warning (G_STRLOC": Unknown window type %d!", window->type);
4720       break;
4721     }
4722    
4723   attributes.title = window->title;
4724   attributes.wmclass_name = window->wmclass_name;
4725   attributes.wmclass_class = window->wmclass_class;
4726   attributes.wclass = GDK_INPUT_OUTPUT;
4727   attributes.visual = gtk_widget_get_visual (widget);
4728   attributes.colormap = gtk_widget_get_colormap (widget);
4729
4730   if (window->has_frame)
4731     {
4732       attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
4733       attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
4734       attributes.event_mask = (GDK_EXPOSURE_MASK |
4735                                GDK_KEY_PRESS_MASK |
4736                                GDK_ENTER_NOTIFY_MASK |
4737                                GDK_LEAVE_NOTIFY_MASK |
4738                                GDK_FOCUS_CHANGE_MASK |
4739                                GDK_STRUCTURE_MASK |
4740                                GDK_BUTTON_MOTION_MASK |
4741                                GDK_POINTER_MOTION_HINT_MASK |
4742                                GDK_BUTTON_PRESS_MASK |
4743                                GDK_BUTTON_RELEASE_MASK);
4744       
4745       attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
4746       
4747       window->frame = gdk_window_new (gtk_widget_get_root_window (widget),
4748                                       &attributes, attributes_mask);
4749                                                  
4750       if (priv->opacity_set)
4751         gdk_window_set_opacity (window->frame, priv->opacity);
4752
4753       gdk_window_set_user_data (window->frame, widget);
4754       
4755       attributes.window_type = GDK_WINDOW_CHILD;
4756       attributes.x = window->frame_left;
4757       attributes.y = window->frame_top;
4758     
4759       attributes_mask = GDK_WA_X | GDK_WA_Y;
4760
4761       parent_window = window->frame;
4762
4763       g_signal_connect (window,
4764                         "event",
4765                         G_CALLBACK (gtk_window_event),
4766                         NULL);
4767     }
4768   else
4769     {
4770       attributes_mask = 0;
4771       parent_window = gtk_widget_get_root_window (widget);
4772     }
4773   
4774   attributes.width = widget->allocation.width;
4775   attributes.height = widget->allocation.height;
4776   attributes.event_mask = gtk_widget_get_events (widget);
4777   attributes.event_mask |= (GDK_EXPOSURE_MASK |
4778                             GDK_KEY_PRESS_MASK |
4779                             GDK_KEY_RELEASE_MASK |
4780                             GDK_ENTER_NOTIFY_MASK |
4781                             GDK_LEAVE_NOTIFY_MASK |
4782                             GDK_FOCUS_CHANGE_MASK |
4783                             GDK_STRUCTURE_MASK);
4784   attributes.type_hint = priv->type_hint;
4785
4786   attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP | GDK_WA_TYPE_HINT;
4787   attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
4788   attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
4789   
4790   widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
4791
4792   if (!window->has_frame && priv->opacity_set)
4793     gdk_window_set_opacity (widget->window, priv->opacity);
4794
4795   gdk_window_enable_synchronized_configure (widget->window);
4796     
4797   gdk_window_set_user_data (widget->window, window);
4798       
4799   widget->style = gtk_style_attach (widget->style, widget->window);
4800   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
4801   if (window->frame)
4802     gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
4803
4804   /* This is a bad hack to set the window background. */
4805   gtk_window_paint (widget, NULL);
4806   
4807   if (window->transient_parent &&
4808       GTK_WIDGET_REALIZED (window->transient_parent))
4809     gdk_window_set_transient_for (widget->window,
4810                                   GTK_WIDGET (window->transient_parent)->window);
4811
4812   if (window->wm_role)
4813     gdk_window_set_role (widget->window, window->wm_role);
4814   
4815   if (!window->decorated)
4816     gdk_window_set_decorations (widget->window, 0);
4817
4818   if (!priv->deletable)
4819     gdk_window_set_functions (widget->window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
4820
4821   if (gtk_window_get_skip_pager_hint (window))
4822     gdk_window_set_skip_pager_hint (widget->window, TRUE);
4823
4824   if (gtk_window_get_skip_taskbar_hint (window))
4825     gdk_window_set_skip_taskbar_hint (widget->window, TRUE);
4826
4827   if (gtk_window_get_accept_focus (window))
4828     gdk_window_set_accept_focus (widget->window, TRUE);
4829   else
4830     gdk_window_set_accept_focus (widget->window, FALSE);
4831
4832   if (gtk_window_get_focus_on_map (window))
4833     gdk_window_set_focus_on_map (widget->window, TRUE);
4834   else
4835     gdk_window_set_focus_on_map (widget->window, FALSE);
4836   
4837   if (window->modal)
4838     gdk_window_set_modal_hint (widget->window, TRUE);
4839   else
4840     gdk_window_set_modal_hint (widget->window, FALSE);
4841     
4842   if (priv->startup_id)
4843     {
4844 #ifdef GDK_WINDOWING_X11
4845       guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
4846       if (timestamp != GDK_CURRENT_TIME)
4847         gdk_x11_window_set_user_time (widget->window, timestamp);
4848 #endif
4849       if (!startup_id_is_fake (priv->startup_id)) 
4850         gdk_window_set_startup_id (widget->window, priv->startup_id);
4851     }
4852
4853   /* Icons */
4854   gtk_window_realize_icon (window);
4855 }
4856
4857 static void
4858 gtk_window_unrealize (GtkWidget *widget)
4859 {
4860   GtkWindow *window;
4861   GtkWindowGeometryInfo *info;
4862
4863   window = GTK_WINDOW (widget);
4864
4865   /* On unrealize, we reset the size of the window such
4866    * that we will re-apply the default sizing stuff
4867    * next time we show the window.
4868    *
4869    * Default positioning is reset on unmap, instead of unrealize.
4870    */
4871   window->need_default_size = TRUE;
4872   info = gtk_window_get_geometry_info (window, FALSE);
4873   if (info)
4874     {
4875       info->resize_width = -1;
4876       info->resize_height = -1;
4877       info->last.configure_request.x = 0;
4878       info->last.configure_request.y = 0;
4879       info->last.configure_request.width = -1;
4880       info->last.configure_request.height = -1;
4881       /* be sure we reset geom hints on re-realize */
4882       info->last.flags = 0;
4883     }
4884   
4885   if (window->frame)
4886     {
4887       gdk_window_set_user_data (window->frame, NULL);
4888       gdk_window_destroy (window->frame);
4889       window->frame = NULL;
4890     }
4891
4892   /* Icons */
4893   gtk_window_unrealize_icon (window);
4894
4895   GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
4896 }
4897
4898 static void
4899 gtk_window_size_request (GtkWidget      *widget,
4900                          GtkRequisition *requisition)
4901 {
4902   GtkWindow *window;
4903   GtkBin *bin;
4904
4905   window = GTK_WINDOW (widget);
4906   bin = GTK_BIN (window);
4907   
4908   requisition->width = GTK_CONTAINER (window)->border_width * 2;
4909   requisition->height = GTK_CONTAINER (window)->border_width * 2;
4910
4911   if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
4912     {
4913       GtkRequisition child_requisition;
4914       
4915       gtk_widget_size_request (bin->child, &child_requisition);
4916
4917       requisition->width += child_requisition.width;
4918       requisition->height += child_requisition.height;
4919     }
4920 }
4921
4922 static void
4923 gtk_window_size_allocate (GtkWidget     *widget,
4924                           GtkAllocation *allocation)
4925 {
4926   GtkWindow *window;
4927   GtkAllocation child_allocation;
4928
4929   window = GTK_WINDOW (widget);
4930   widget->allocation = *allocation;
4931
4932   if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
4933     {
4934       child_allocation.x = GTK_CONTAINER (window)->border_width;
4935       child_allocation.y = GTK_CONTAINER (window)->border_width;
4936       child_allocation.width =
4937         MAX (1, (gint)allocation->width - child_allocation.x * 2);
4938       child_allocation.height =
4939         MAX (1, (gint)allocation->height - child_allocation.y * 2);
4940
4941       gtk_widget_size_allocate (window->bin.child, &child_allocation);
4942     }
4943
4944   if (GTK_WIDGET_REALIZED (widget) && window->frame)
4945     {
4946       gdk_window_resize (window->frame,
4947                          allocation->width + window->frame_left + window->frame_right,
4948                          allocation->height + window->frame_top + window->frame_bottom);
4949     }
4950 }
4951
4952 static gint
4953 gtk_window_event (GtkWidget *widget, GdkEvent *event)
4954 {
4955   GtkWindow *window;
4956   gboolean return_val;
4957
4958   window = GTK_WINDOW (widget);
4959
4960   if (window->frame && (event->any.window == window->frame))
4961     {
4962       if ((event->type != GDK_KEY_PRESS) &&
4963           (event->type != GDK_KEY_RELEASE) &&
4964           (event->type != GDK_FOCUS_CHANGE))
4965         {
4966           g_signal_stop_emission_by_name (widget, "event");
4967           return_val = FALSE;
4968           g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
4969           return TRUE;
4970         }
4971       else
4972         {
4973           g_object_unref (event->any.window);
4974           event->any.window = g_object_ref (widget->window);
4975         }
4976     }
4977
4978   return FALSE;
4979 }
4980
4981 static gboolean
4982 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
4983 {
4984   GdkEventConfigure *configure_event;
4985   GdkRectangle rect;
4986
4987   switch (event->type)
4988     {
4989     case GDK_CONFIGURE:
4990       configure_event = (GdkEventConfigure *)event;
4991       
4992       /* Invalidate the decorations */
4993       rect.x = 0;
4994       rect.y = 0;
4995       rect.width = configure_event->width;
4996       rect.height = configure_event->height;
4997       
4998       gdk_window_invalidate_rect (window->frame, &rect, FALSE);
4999
5000       /* Pass on the (modified) configure event */
5001       configure_event->width -= window->frame_left + window->frame_right;
5002       configure_event->height -= window->frame_top + window->frame_bottom;
5003       return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
5004       break;
5005     default:
5006       break;
5007     }
5008   return FALSE;
5009 }
5010
5011 static gint
5012 gtk_window_configure_event (GtkWidget         *widget,
5013                             GdkEventConfigure *event)
5014 {
5015   GtkWindow *window = GTK_WINDOW (widget);
5016   gboolean expected_reply = window->configure_request_count > 0;
5017
5018   /* window->configure_request_count incremented for each 
5019    * configure request, and decremented to a min of 0 for
5020    * each configure notify.
5021    *
5022    * All it means is that we know we will get at least
5023    * window->configure_request_count more configure notifies.
5024    * We could get more configure notifies than that; some
5025    * of the configure notifies we get may be unrelated to
5026    * the configure requests. But we will get at least
5027    * window->configure_request_count notifies.
5028    */
5029
5030   if (window->configure_request_count > 0)
5031     {
5032       window->configure_request_count -= 1;
5033       gdk_window_thaw_toplevel_updates_libgtk_only (widget->window);
5034     }
5035   
5036   /* As an optimization, we avoid a resize when possible.
5037    *
5038    * The only times we can avoid a resize are:
5039    *   - we know only the position changed, not the size
5040    *   - we know we have made more requests and so will get more
5041    *     notifies and can wait to resize when we get them
5042    */
5043   
5044   if (!expected_reply &&
5045       (widget->allocation.width == event->width &&
5046        widget->allocation.height == event->height))
5047     {
5048       gdk_window_configure_finished (widget->window);
5049       return TRUE;
5050     }
5051
5052   /*
5053    * If we do need to resize, we do that by:
5054    *   - filling in widget->allocation with the new size
5055    *   - setting configure_notify_received to TRUE
5056    *     for use in gtk_window_move_resize()
5057    *   - queueing a resize, leading to invocation of
5058    *     gtk_window_move_resize() in an idle handler
5059    *
5060    */
5061   
5062   window->configure_notify_received = TRUE;
5063   
5064   widget->allocation.width = event->width;
5065   widget->allocation.height = event->height;
5066   
5067   _gtk_container_queue_resize (GTK_CONTAINER (widget));
5068   
5069   return TRUE;
5070 }
5071
5072 /* the accel_key and accel_mods fields of the key have to be setup
5073  * upon calling this function. it'll then return whether that key
5074  * is at all used as accelerator, and if so will OR in the
5075  * accel_flags member of the key.
5076  */
5077 gboolean
5078 _gtk_window_query_nonaccels (GtkWindow      *window,
5079                              guint           accel_key,
5080                              GdkModifierType accel_mods)
5081 {
5082   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5083
5084   /* movement keys are considered locked accels */
5085   if (!accel_mods)
5086     {
5087       static const guint bindings[] = {
5088         GDK_space, GDK_KP_Space, GDK_Return, GDK_ISO_Enter, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
5089         GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
5090       };
5091       guint i;
5092       
5093       for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5094         if (bindings[i] == accel_key)
5095           return TRUE;
5096     }
5097
5098   /* mnemonics are considered locked accels */
5099   if (accel_mods == window->mnemonic_modifier)
5100     {
5101       GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
5102       if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
5103         return TRUE;
5104     }
5105
5106   return FALSE;
5107 }
5108
5109 /**
5110  * gtk_window_propagate_key_event:
5111  * @window:  a #GtkWindow
5112  * @event:   a #GdkEventKey
5113  *
5114  * Propagate a key press or release event to the focus widget and
5115  * up the focus container chain until a widget handles @event.
5116  * This is normally called by the default ::key_press_event and
5117  * ::key_release_event handlers for toplevel windows,
5118  * however in some cases it may be useful to call this directly when
5119  * overriding the standard key handling for a toplevel window.
5120  *
5121  * Return value: %TRUE if a widget in the focus chain handled the event.
5122  **/
5123 gboolean
5124 gtk_window_propagate_key_event (GtkWindow        *window,
5125                                 GdkEventKey      *event)
5126 {
5127   gboolean handled = FALSE;
5128   GtkWidget *widget, *focus;
5129
5130   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5131
5132   widget = GTK_WIDGET (window);
5133   focus = window->focus_widget;
5134   if (focus)
5135     g_object_ref (focus);
5136   
5137   while (!handled &&
5138          focus && focus != widget &&
5139          gtk_widget_get_toplevel (focus) == widget)
5140     {
5141       GtkWidget *parent;
5142       
5143       if (GTK_WIDGET_IS_SENSITIVE (focus))
5144         handled = gtk_widget_event (focus, (GdkEvent*) event);
5145       
5146       parent = focus->parent;
5147       if (parent)
5148         g_object_ref (parent);
5149       
5150       g_object_unref (focus);
5151       
5152       focus = parent;
5153     }
5154   
5155   if (focus)
5156     g_object_unref (focus);
5157
5158   return handled;
5159 }
5160
5161 static gint
5162 gtk_window_key_press_event (GtkWidget   *widget,
5163                             GdkEventKey *event)
5164 {
5165   GtkWindow *window = GTK_WINDOW (widget);
5166   gboolean handled = FALSE;
5167
5168   /* handle mnemonics and accelerators */
5169   if (!handled)
5170     handled = gtk_window_activate_key (window, event);
5171
5172   /* handle focus widget key events */
5173   if (!handled)
5174     handled = gtk_window_propagate_key_event (window, event);
5175
5176   /* Chain up, invokes binding set */
5177   if (!handled)
5178     handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
5179
5180   return handled;
5181 }
5182
5183 static gint
5184 gtk_window_key_release_event (GtkWidget   *widget,
5185                               GdkEventKey *event)
5186 {
5187   GtkWindow *window = GTK_WINDOW (widget);
5188   gboolean handled = FALSE;
5189
5190   /* handle focus widget key events */
5191   if (!handled)
5192     handled = gtk_window_propagate_key_event (window, event);
5193
5194   /* Chain up, invokes binding set */
5195   if (!handled)
5196     handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
5197
5198   return handled;
5199 }
5200
5201 static void
5202 gtk_window_real_activate_default (GtkWindow *window)
5203 {
5204   gtk_window_activate_default (window);
5205 }
5206
5207 static void
5208 gtk_window_real_activate_focus (GtkWindow *window)
5209 {
5210   gtk_window_activate_focus (window);
5211 }
5212
5213 static void
5214 gtk_window_move_focus (GtkWindow       *window,
5215                        GtkDirectionType dir)
5216 {
5217   gtk_widget_child_focus (GTK_WIDGET (window), dir);
5218   
5219   if (!GTK_CONTAINER (window)->focus_child)
5220     gtk_window_set_focus (window, NULL);
5221 }
5222
5223 static gint
5224 gtk_window_enter_notify_event (GtkWidget        *widget,
5225                                GdkEventCrossing *event)
5226 {
5227   return FALSE;
5228 }
5229
5230 static gint
5231 gtk_window_leave_notify_event (GtkWidget        *widget,
5232                                GdkEventCrossing *event)
5233 {
5234   return FALSE;
5235 }
5236
5237 static void
5238 do_focus_change (GtkWidget *widget,
5239                  gboolean   in)
5240 {
5241   GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
5242   
5243   g_object_ref (widget);
5244   
5245   if (in)
5246     GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
5247   else
5248     GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
5249   
5250   fevent->focus_change.type = GDK_FOCUS_CHANGE;
5251   fevent->focus_change.window = widget->window;
5252   if (widget->window)
5253     g_object_ref (widget->window);
5254   fevent->focus_change.in = in;
5255   
5256   gtk_widget_event (widget, fevent);
5257   
5258   g_object_notify (G_OBJECT (widget), "has-focus");
5259
5260   g_object_unref (widget);
5261   gdk_event_free (fevent);
5262 }
5263
5264 static gint
5265 gtk_window_focus_in_event (GtkWidget     *widget,
5266                            GdkEventFocus *event)
5267 {
5268   GtkWindow *window = GTK_WINDOW (widget);
5269
5270   /* It appears spurious focus in events can occur when
5271    *  the window is hidden. So we'll just check to see if
5272    *  the window is visible before actually handling the
5273    *  event
5274    */
5275   if (GTK_WIDGET_VISIBLE (widget))
5276     {
5277       _gtk_window_set_has_toplevel_focus (window, TRUE);
5278       _gtk_window_set_is_active (window, TRUE);
5279     }
5280       
5281   return FALSE;
5282 }
5283
5284 static gint
5285 gtk_window_focus_out_event (GtkWidget     *widget,
5286                             GdkEventFocus *event)
5287 {
5288   GtkWindow *window = GTK_WINDOW (widget);
5289
5290   _gtk_window_set_has_toplevel_focus (window, FALSE);
5291   _gtk_window_set_is_active (window, FALSE);
5292
5293   return FALSE;
5294 }
5295
5296 static GdkAtom atom_rcfiles = GDK_NONE;
5297 static GdkAtom atom_iconthemes = GDK_NONE;
5298
5299 static void
5300 send_client_message_to_embedded_windows (GtkWidget *widget,
5301                                          GdkAtom    message_type)
5302 {
5303   GList *embedded_windows;
5304
5305   embedded_windows = g_object_get_qdata (G_OBJECT (widget), quark_gtk_embedded);
5306   if (embedded_windows)
5307     {
5308       GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
5309       int i;
5310       
5311       for (i = 0; i < 5; i++)
5312         send_event->client.data.l[i] = 0;
5313       send_event->client.data_format = 32;
5314       send_event->client.message_type = message_type;
5315       
5316       while (embedded_windows)
5317         {
5318           GdkNativeWindow xid = (GdkNativeWindow) embedded_windows->data;
5319           gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
5320           embedded_windows = embedded_windows->next;
5321         }
5322
5323       gdk_event_free (send_event);
5324     }
5325 }
5326
5327 static gint
5328 gtk_window_client_event (GtkWidget      *widget,
5329                          GdkEventClient *event)
5330 {
5331   if (!atom_rcfiles)
5332     {
5333       atom_rcfiles = gdk_atom_intern_static_string ("_GTK_READ_RCFILES");
5334       atom_iconthemes = gdk_atom_intern_static_string ("_GTK_LOAD_ICONTHEMES");
5335     }
5336
5337   if (event->message_type == atom_rcfiles) 
5338     {
5339       send_client_message_to_embedded_windows (widget, atom_rcfiles);
5340       gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
5341     }
5342
5343   if (event->message_type == atom_iconthemes) 
5344     {
5345       send_client_message_to_embedded_windows (widget, atom_iconthemes);
5346       _gtk_icon_theme_check_reload (gtk_widget_get_display (widget));    
5347     }
5348
5349   return FALSE;
5350 }
5351
5352 static void
5353 gtk_window_check_resize (GtkContainer *container)
5354 {
5355   GtkWindow *window = GTK_WINDOW (container);
5356
5357   if (GTK_WIDGET_VISIBLE (container))
5358     gtk_window_move_resize (window);
5359 }
5360
5361 static gboolean
5362 gtk_window_focus (GtkWidget        *widget,
5363                   GtkDirectionType  direction)
5364 {
5365   GtkBin *bin;
5366   GtkWindow *window;
5367   GtkContainer *container;
5368   GtkWidget *old_focus_child;
5369   GtkWidget *parent;
5370
5371   container = GTK_CONTAINER (widget);
5372   window = GTK_WINDOW (widget);
5373   bin = GTK_BIN (widget);
5374
5375   old_focus_child = container->focus_child;
5376   
5377   /* We need a special implementation here to deal properly with wrapping
5378    * around in the tab chain without the danger of going into an
5379    * infinite loop.
5380    */
5381   if (old_focus_child)
5382     {
5383       if (gtk_widget_child_focus (old_focus_child, direction))
5384         return TRUE;
5385     }
5386
5387   if (window->focus_widget)
5388     {
5389       if (direction == GTK_DIR_LEFT ||
5390           direction == GTK_DIR_RIGHT ||
5391           direction == GTK_DIR_UP ||
5392           direction == GTK_DIR_DOWN)
5393         {
5394           return FALSE;
5395         }
5396       
5397       /* Wrapped off the end, clear the focus setting for the toplpevel */
5398       parent = window->focus_widget->parent;
5399       while (parent)
5400         {
5401           gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
5402           parent = GTK_WIDGET (parent)->parent;
5403         }
5404       
5405       gtk_window_set_focus (GTK_WINDOW (container), NULL);
5406     }
5407
5408   /* Now try to focus the first widget in the window */
5409   if (bin->child)
5410     {
5411       if (gtk_widget_child_focus (bin->child, direction))
5412         return TRUE;
5413     }
5414
5415   return FALSE;
5416 }
5417
5418 static void
5419 gtk_window_real_set_focus (GtkWindow *window,
5420                            GtkWidget *focus)
5421 {
5422   GtkWidget *old_focus = window->focus_widget;
5423   gboolean had_default = FALSE;
5424   gboolean focus_had_default = FALSE;
5425   gboolean old_focus_had_default = FALSE;
5426
5427   if (old_focus)
5428     {
5429       g_object_ref (old_focus);
5430       g_object_freeze_notify (G_OBJECT (old_focus));
5431       old_focus_had_default = GTK_WIDGET_HAS_DEFAULT (old_focus);
5432     }
5433   if (focus)
5434     {
5435       g_object_ref (focus);
5436       g_object_freeze_notify (G_OBJECT (focus));
5437       focus_had_default = GTK_WIDGET_HAS_DEFAULT (focus);
5438     }
5439   
5440   if (window->default_widget)
5441     had_default = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
5442   
5443   if (window->focus_widget)
5444     {
5445       if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
5446           (window->focus_widget != window->default_widget))
5447         {
5448           GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
5449           gtk_widget_queue_draw (window->focus_widget);
5450           
5451           if (window->default_widget)
5452             GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
5453         }
5454
5455       window->focus_widget = NULL;
5456
5457       if (window->has_focus)
5458         do_focus_change (old_focus, FALSE);
5459
5460       g_object_notify (G_OBJECT (old_focus), "is-focus");
5461     }
5462
5463   /* The above notifications may have set a new focus widget,
5464    * if so, we don't want to override it.
5465    */
5466   if (focus && !window->focus_widget)
5467     {
5468       window->focus_widget = focus;
5469   
5470       if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
5471           (window->focus_widget != window->default_widget))
5472         {
5473           if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
5474             GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
5475
5476           if (window->default_widget)
5477             GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
5478         }
5479
5480       if (window->has_focus)
5481         do_focus_change (window->focus_widget, TRUE);
5482
5483       g_object_notify (G_OBJECT (window->focus_widget), "is-focus");
5484     }
5485
5486   /* If the default widget changed, a redraw will have been queued
5487    * on the old and new default widgets by gtk_window_set_default(), so
5488    * we only have to worry about the case where it didn't change.
5489    * We'll sometimes queue a draw twice on the new widget but that
5490    * is harmless.
5491    */
5492   if (window->default_widget &&
5493       (had_default != GTK_WIDGET_HAS_DEFAULT (window->default_widget)))
5494     gtk_widget_queue_draw (window->default_widget);
5495   
5496   if (old_focus)
5497     {
5498       if (old_focus_had_default != GTK_WIDGET_HAS_DEFAULT (old_focus))
5499         gtk_widget_queue_draw (old_focus);
5500         
5501       g_object_thaw_notify (G_OBJECT (old_focus));
5502       g_object_unref (old_focus);
5503     }
5504   if (focus)
5505     {
5506       if (focus_had_default != GTK_WIDGET_HAS_DEFAULT (focus))
5507         gtk_widget_queue_draw (focus);
5508
5509       g_object_thaw_notify (G_OBJECT (focus));
5510       g_object_unref (focus);
5511     }
5512 }
5513
5514 /**
5515  * _gtk_window_unset_focus_and_default:
5516  * @window: a #GtkWindow
5517  * @widget: a widget inside of @window
5518  * 
5519  * Checks whether the focus and default widgets of @window are
5520  * @widget or a descendent of @widget, and if so, unset them.
5521  **/
5522 void
5523 _gtk_window_unset_focus_and_default (GtkWindow *window,
5524                                      GtkWidget *widget)
5525
5526 {
5527   GtkWidget *child;
5528
5529   g_object_ref (window);
5530   g_object_ref (widget);
5531       
5532   if (GTK_CONTAINER (widget->parent)->focus_child == widget)
5533     {
5534       child = window->focus_widget;
5535       
5536       while (child && child != widget)
5537         child = child->parent;
5538   
5539       if (child == widget)
5540         gtk_window_set_focus (GTK_WINDOW (window), NULL);
5541     }
5542       
5543   child = window->default_widget;
5544       
5545   while (child && child != widget)
5546     child = child->parent;
5547       
5548   if (child == widget)
5549     gtk_window_set_default (window, NULL);
5550   
5551   g_object_unref (widget);
5552   g_object_unref (window);
5553 }
5554
5555 /*********************************
5556  * Functions related to resizing *
5557  *********************************/
5558
5559 /* This function doesn't constrain to geometry hints */
5560 static void 
5561 gtk_window_compute_configure_request_size (GtkWindow *window,
5562                                            guint     *width,
5563                                            guint     *height)
5564 {
5565   GtkRequisition requisition;
5566   GtkWindowGeometryInfo *info;
5567   GtkWidget *widget;
5568
5569   /* Preconditions:
5570    *  - we've done a size request
5571    */
5572   
5573   widget = GTK_WIDGET (window);
5574
5575   info = gtk_window_get_geometry_info (window, FALSE);
5576   
5577   if (window->need_default_size)
5578     {
5579       gtk_widget_get_child_requisition (widget, &requisition);
5580
5581       /* Default to requisition */
5582       *width = requisition.width;
5583       *height = requisition.height;
5584
5585       /* If window is empty so requests 0, default to random nonzero size */
5586        if (*width == 0 && *height == 0)
5587          {
5588            *width = 200;
5589            *height = 200;
5590          }
5591
5592        /* Override requisition with default size */
5593
5594        if (info)
5595          {
5596            gint base_width = 0;
5597            gint base_height = 0;
5598            gint min_width = 0;
5599            gint min_height = 0;
5600            gint width_inc = 1;
5601            gint height_inc = 1;
5602            
5603            if (info->default_is_geometry &&
5604                (info->default_width > 0 || info->default_height > 0))
5605              {
5606                GdkGeometry geometry;
5607                guint flags;
5608                
5609                gtk_window_compute_hints (window, &geometry, &flags);
5610
5611                if (flags & GDK_HINT_BASE_SIZE)
5612                  {
5613                    base_width = geometry.base_width;
5614                    base_height = geometry.base_height;
5615                  }
5616                if (flags & GDK_HINT_MIN_SIZE)
5617                  {
5618                    min_width = geometry.min_width;
5619                    min_height = geometry.min_height;
5620                  }
5621                if (flags & GDK_HINT_RESIZE_INC)
5622                  {
5623                    width_inc = geometry.width_inc;
5624                    height_inc = geometry.height_inc;
5625                  }
5626              }
5627              
5628            if (info->default_width > 0)
5629              *width = MAX (info->default_width * width_inc + base_width, min_width);
5630            
5631            if (info->default_height > 0)
5632              *height = MAX (info->default_height * height_inc + base_height, min_height);
5633          }
5634     }
5635   else
5636     {
5637       /* Default to keeping current size */
5638       *width = widget->allocation.width;
5639       *height = widget->allocation.height;
5640     }
5641
5642   /* Override any size with gtk_window_resize() values */
5643   if (info)
5644     {
5645       if (info->resize_width > 0)
5646         *width = info->resize_width;
5647
5648       if (info->resize_height > 0)
5649         *height = info->resize_height;
5650     }
5651
5652   /* Don't ever request zero width or height, its not supported by
5653      gdk. The size allocation code will round it to 1 anyway but if
5654      we do it then the value returned from this function will is
5655      not comparable to the size allocation read from the GtkWindow. */
5656   *width = MAX (*width, 1);
5657   *height = MAX (*height, 1);
5658 }
5659
5660 static GtkWindowPosition
5661 get_effective_position (GtkWindow *window)
5662 {
5663   GtkWindowPosition pos = window->position;
5664   if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
5665       (window->transient_parent == NULL ||
5666        !GTK_WIDGET_MAPPED (window->transient_parent)))
5667     pos = GTK_WIN_POS_NONE;
5668
5669   return pos;
5670 }
5671
5672 static int
5673 get_center_monitor_of_window (GtkWindow *window)
5674 {
5675   /* We could try to sort out the relative positions of the monitors and
5676    * stuff, or we could just be losers and assume you have a row
5677    * or column of monitors.
5678    */
5679   return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
5680 }
5681
5682 static int
5683 get_monitor_containing_pointer (GtkWindow *window)
5684 {
5685   gint px, py;
5686   gint monitor_num;
5687   GdkScreen *window_screen;
5688   GdkScreen *pointer_screen;
5689
5690   window_screen = gtk_window_check_screen (window);
5691   gdk_display_get_pointer (gdk_screen_get_display (window_screen),
5692                            &pointer_screen,
5693                            &px, &py, NULL);
5694
5695   if (pointer_screen == window_screen)
5696     monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
5697   else
5698     monitor_num = -1;
5699
5700   return monitor_num;
5701 }
5702
5703 static void
5704 center_window_on_monitor (GtkWindow *window,
5705                           gint       w,
5706                           gint       h,
5707                           gint      *x,
5708                           gint      *y)
5709 {
5710   GdkRectangle monitor;
5711   int monitor_num;
5712
5713   monitor_num = get_monitor_containing_pointer (window);
5714   
5715   if (monitor_num == -1)
5716     monitor_num = get_center_monitor_of_window (window);
5717
5718   gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
5719                                    monitor_num, &monitor);
5720   
5721   *x = (monitor.width - w) / 2 + monitor.x;
5722   *y = (monitor.height - h) / 2 + monitor.y;
5723
5724   /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
5725    * and WM decorations.
5726    */
5727   if (*x < monitor.x)
5728     *x = monitor.x;
5729   if (*y < monitor.y)
5730     *y = monitor.y;
5731 }
5732
5733 static void
5734 clamp (gint *base,
5735        gint  extent,
5736        gint  clamp_base,
5737        gint  clamp_extent)
5738 {
5739   if (extent > clamp_extent)
5740     /* Center */
5741     *base = clamp_base + clamp_extent/2 - extent/2;
5742   else if (*base < clamp_base)
5743     *base = clamp_base;
5744   else if (*base + extent > clamp_base + clamp_extent)
5745     *base = clamp_base + clamp_extent - extent;
5746 }
5747
5748 static void
5749 clamp_window_to_rectangle (gint               *x,
5750                            gint               *y,
5751                            gint                w,
5752                            gint                h,
5753                            const GdkRectangle *rect)
5754 {
5755 #ifdef DEBUGGING_OUTPUT
5756   g_print ("%s: %+d%+d %dx%d: %+d%+d: %dx%d", G_STRFUNC, rect->x, rect->y, rect->width, rect->height, *x, *y, w, h);
5757 #endif
5758
5759   /* If it is too large, center it. If it fits on the monitor but is
5760    * partially outside, move it to the closest edge. Do this
5761    * separately in x and y directions.
5762    */
5763   clamp (x, w, rect->x, rect->width);
5764   clamp (y, h, rect->y, rect->height);
5765 #ifdef DEBUGGING_OUTPUT
5766   g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
5767 #endif
5768 }
5769
5770
5771 static void
5772 gtk_window_compute_configure_request (GtkWindow    *window,
5773                                       GdkRectangle *request,
5774                                       GdkGeometry  *geometry,
5775                                       guint        *flags)
5776 {
5777   GdkGeometry new_geometry;
5778   guint new_flags;
5779   int w, h;
5780   GtkWidget *widget;
5781   GtkWindowPosition pos;
5782   GtkWidget *parent_widget;
5783   GtkWindowGeometryInfo *info;
5784   GdkScreen *screen;
5785   int x, y;
5786   
5787   widget = GTK_WIDGET (window);
5788
5789   screen = gtk_window_check_screen (window);
5790   
5791   gtk_widget_size_request (widget, NULL);
5792   gtk_window_compute_configure_request_size (window, (guint *)&w, (guint *)&h);
5793   
5794   gtk_window_compute_hints (window, &new_geometry, &new_flags);
5795   gtk_window_constrain_size (window,
5796                              &new_geometry, new_flags,
5797                              w, h,
5798                              &w, &h);
5799
5800   parent_widget = (GtkWidget*) window->transient_parent;
5801   
5802   pos = get_effective_position (window);
5803   info = gtk_window_get_geometry_info (window, FALSE);
5804   
5805   /* by default, don't change position requested */
5806   if (info)
5807     {
5808       x = info->last.configure_request.x;
5809       y = info->last.configure_request.y;
5810     }
5811   else
5812     {
5813       x = 0;
5814       y = 0;
5815     }
5816
5817
5818   if (window->need_default_position)
5819     {
5820
5821       /* FIXME this all interrelates with window gravity.
5822        * For most of them I think we want to set GRAVITY_CENTER.
5823        *
5824        * Not sure how to go about that.
5825        */
5826       
5827       switch (pos)
5828         {
5829           /* here we are only handling CENTER_ALWAYS
5830            * as it relates to default positioning,
5831            * where it's equivalent to simply CENTER
5832            */
5833         case GTK_WIN_POS_CENTER_ALWAYS:
5834         case GTK_WIN_POS_CENTER:
5835           center_window_on_monitor (window, w, h, &x, &y);
5836           break;
5837       
5838         case GTK_WIN_POS_CENTER_ON_PARENT:
5839           {
5840             gint monitor_num;
5841             GdkRectangle monitor;
5842             gint ox, oy;
5843             
5844             g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
5845
5846             if (parent_widget->window != NULL)
5847               monitor_num = gdk_screen_get_monitor_at_window (screen,
5848                                                               parent_widget->window);
5849             else
5850               monitor_num = -1;
5851             
5852             gdk_window_get_origin (parent_widget->window,
5853                                    &ox, &oy);
5854             
5855             x = ox + (parent_widget->allocation.width - w) / 2;
5856             y = oy + (parent_widget->allocation.height - h) / 2;
5857             
5858             /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
5859              * WM decorations. If parent wasn't on a monitor, just
5860              * give up.
5861              */
5862             if (monitor_num >= 0)
5863               {
5864                 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
5865                 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
5866               }
5867           }
5868           break;
5869
5870         case GTK_WIN_POS_MOUSE:
5871           {
5872             gint screen_width = gdk_screen_get_width (screen);
5873             gint screen_height = gdk_screen_get_height (screen);
5874             gint monitor_num;
5875             GdkRectangle monitor;
5876             GdkScreen *pointer_screen;
5877             gint px, py;
5878             
5879             gdk_display_get_pointer (gdk_screen_get_display (screen),
5880                                      &pointer_screen,
5881                                      &px, &py, NULL);
5882
5883             if (pointer_screen == screen)
5884               monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
5885             else
5886               monitor_num = -1;
5887             
5888             x = px - w / 2;
5889             y = py - h / 2;
5890             x = CLAMP (x, 0, screen_width - w);
5891             y = CLAMP (y, 0, screen_height - h);
5892
5893             /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
5894              * WM decorations. Don't try to figure out what's going
5895              * on if the mouse wasn't inside a monitor.
5896              */
5897             if (monitor_num >= 0)
5898               {
5899                 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
5900                 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
5901               }
5902           }
5903           break;
5904
5905         default:
5906           break;
5907         }
5908     } /* if (window->need_default_position) */
5909
5910   if (window->need_default_position && info &&
5911       info->initial_pos_set)
5912     {
5913       x = info->initial_x;
5914       y = info->initial_y;
5915       gtk_window_constrain_position (window, w, h, &x, &y);
5916     }
5917   
5918   request->x = x;
5919   request->y = y;
5920   request->width = w;
5921   request->height = h;
5922
5923   if (geometry)
5924     *geometry = new_geometry;
5925   if (flags)
5926     *flags = new_flags;
5927 }
5928
5929 static void
5930 gtk_window_constrain_position (GtkWindow    *window,
5931                                gint          new_width,
5932                                gint          new_height,
5933                                gint         *x,
5934                                gint         *y)
5935 {
5936   /* See long comments in gtk_window_move_resize()
5937    * on when it's safe to call this function.
5938    */
5939   if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
5940     {
5941       gint center_x, center_y;
5942
5943       center_window_on_monitor (window, new_width, new_height, &center_x, &center_y);
5944       
5945       *x = center_x;
5946       *y = center_y;
5947     }
5948 }
5949
5950 static void
5951 gtk_window_move_resize (GtkWindow *window)
5952 {
5953   /* Overview:
5954    *
5955    * First we determine whether any information has changed that would
5956    * cause us to revise our last configure request.  If we would send
5957    * a different configure request from last time, then
5958    * configure_request_size_changed = TRUE or
5959    * configure_request_pos_changed = TRUE. configure_request_size_changed
5960    * may be true due to new hints, a gtk_window_resize(), or whatever.
5961    * configure_request_pos_changed may be true due to gtk_window_set_position()
5962    * or gtk_window_move().
5963    *
5964    * If the configure request has changed, we send off a new one.  To
5965    * ensure GTK+ invariants are maintained (resize queue does what it
5966    * should), we go ahead and size_allocate the requested size in this
5967    * function.
5968    *
5969    * If the configure request has not changed, we don't ever resend
5970    * it, because it could mean fighting the user or window manager.
5971    *
5972    * 
5973    *   To prepare the configure request, we come up with a base size/pos:
5974    *      - the one from gtk_window_move()/gtk_window_resize()
5975    *      - else default_width, default_height if we haven't ever
5976    *        been mapped
5977    *      - else the size request if we haven't ever been mapped,
5978    *        as a substitute default size
5979    *      - else the current size of the window, as received from
5980    *        configure notifies (i.e. the current allocation)
5981    *
5982    *   If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
5983    *   the position request to be centered.
5984    */
5985   GtkWidget *widget;
5986   GtkContainer *container;
5987   GtkWindowGeometryInfo *info;
5988   GdkGeometry new_geometry;
5989   guint new_flags;
5990   GdkRectangle new_request;
5991   gboolean configure_request_size_changed;
5992   gboolean configure_request_pos_changed;
5993   gboolean hints_changed; /* do we need to send these again */
5994   GtkWindowLastGeometryInfo saved_last_info;
5995   
5996   widget = GTK_WIDGET (window);
5997   container = GTK_CONTAINER (widget);
5998   info = gtk_window_get_geometry_info (window, TRUE);
5999   
6000   configure_request_size_changed = FALSE;
6001   configure_request_pos_changed = FALSE;
6002   
6003   gtk_window_compute_configure_request (window, &new_request,
6004                                         &new_geometry, &new_flags);  
6005   
6006   /* This check implies the invariant that we never set info->last
6007    * without setting the hints and sending off a configure request.
6008    *
6009    * If we change info->last without sending the request, we may
6010    * miss a request.
6011    */
6012   if (info->last.configure_request.x != new_request.x ||
6013       info->last.configure_request.y != new_request.y)
6014     configure_request_pos_changed = TRUE;
6015
6016   if ((info->last.configure_request.width != new_request.width ||
6017        info->last.configure_request.height != new_request.height))
6018     configure_request_size_changed = TRUE;
6019   
6020   hints_changed = FALSE;
6021   
6022   if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
6023                                  &new_geometry, new_flags))
6024     {
6025       hints_changed = TRUE;
6026     }
6027   
6028   /* Position Constraints
6029    * ====================
6030    * 
6031    * POS_CENTER_ALWAYS is conceptually a constraint rather than
6032    * a default. The other POS_ values are used only when the
6033    * window is shown, not after that.
6034    * 
6035    * However, we can't implement a position constraint as
6036    * "anytime the window size changes, center the window"
6037    * because this may well end up fighting the WM or user.  In
6038    * fact it gets in an infinite loop with at least one WM.
6039    *
6040    * Basically, applications are in no way in a position to
6041    * constrain the position of a window, with one exception:
6042    * override redirect windows. (Really the intended purpose
6043    * of CENTER_ALWAYS anyhow, I would think.)
6044    *
6045    * So the way we implement this "constraint" is to say that when WE
6046    * cause a move or resize, i.e. we make a configure request changing
6047    * window size, we recompute the CENTER_ALWAYS position to reflect
6048    * the new window size, and include it in our request.  Also, if we
6049    * just turned on CENTER_ALWAYS we snap to center with a new
6050    * request.  Otherwise, if we are just NOTIFIED of a move or resize
6051    * done by someone else e.g. the window manager, we do NOT send a
6052    * new configure request.
6053    *
6054    * For override redirect windows, this works fine; all window
6055    * sizes are from our configure requests. For managed windows,
6056    * it is at least semi-sane, though who knows what the
6057    * app author is thinking.
6058    */
6059
6060   /* This condition should be kept in sync with the condition later on
6061    * that determines whether we send a configure request.  i.e. we
6062    * should do this position constraining anytime we were going to
6063    * send a configure request anyhow, plus when constraints have
6064    * changed.
6065    */
6066   if (configure_request_pos_changed ||
6067       configure_request_size_changed ||
6068       hints_changed ||
6069       info->position_constraints_changed)
6070     {
6071       /* We request the constrained position if:
6072        *  - we were changing position, and need to clamp
6073        *    the change to the constraint
6074        *  - we're changing the size anyway
6075        *  - set_position() was called to toggle CENTER_ALWAYS on
6076        */
6077
6078       gtk_window_constrain_position (window,
6079                                      new_request.width,
6080                                      new_request.height,
6081                                      &new_request.x,
6082                                      &new_request.y);
6083       
6084       /* Update whether we need to request a move */
6085       if (info->last.configure_request.x != new_request.x ||
6086           info->last.configure_request.y != new_request.y)
6087         configure_request_pos_changed = TRUE;
6088       else
6089         configure_request_pos_changed = FALSE;
6090     }
6091
6092 #if 0
6093   if (window->type == GTK_WINDOW_TOPLEVEL)
6094     {
6095       int notify_x, notify_y;
6096
6097       /* this is the position from the last configure notify */
6098       gdk_window_get_position (widget->window, &notify_x, &notify_y);
6099     
6100       g_message ("--- %s ---\n"
6101                  "last  : %d,%d\t%d x %d\n"
6102                  "this  : %d,%d\t%d x %d\n"
6103                  "alloc : %d,%d\t%d x %d\n"
6104                  "req   :      \t%d x %d\n"
6105                  "resize:      \t%d x %d\n" 
6106                  "size_changed: %d pos_changed: %d hints_changed: %d\n"
6107                  "configure_notify_received: %d\n"
6108                  "configure_request_count: %d\n"
6109                  "position_constraints_changed: %d\n",
6110                  window->title ? window->title : "(no title)",
6111                  info->last.configure_request.x,
6112                  info->last.configure_request.y,
6113                  info->last.configure_request.width,
6114                  info->last.configure_request.height,
6115                  new_request.x,
6116                  new_request.y,
6117                  new_request.width,
6118                  new_request.height,
6119                  notify_x, notify_y,
6120                  widget->allocation.width,
6121                  widget->allocation.height,
6122                  widget->requisition.width,
6123                  widget->requisition.height,
6124                  info->resize_width,
6125                  info->resize_height,
6126                  configure_request_pos_changed,
6127                  configure_request_size_changed,
6128                  hints_changed,
6129                  window->configure_notify_received,
6130                  window->configure_request_count,
6131                  info->position_constraints_changed);
6132     }
6133 #endif
6134   
6135   saved_last_info = info->last;
6136   info->last.geometry = new_geometry;
6137   info->last.flags = new_flags;
6138   info->last.configure_request = new_request;
6139   
6140   /* need to set PPosition so the WM will look at our position,
6141    * but we don't want to count PPosition coming and going as a hints
6142    * change for future iterations. So we saved info->last prior to
6143    * this.
6144    */
6145   
6146   /* Also, if the initial position was explicitly set, then we always
6147    * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
6148    * work.
6149    */
6150
6151   /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
6152    * this is an initial map
6153    */
6154   
6155   if ((configure_request_pos_changed ||
6156        info->initial_pos_set ||
6157        (window->need_default_position &&
6158         get_effective_position (window) != GTK_WIN_POS_NONE)) &&
6159       (new_flags & GDK_HINT_POS) == 0)
6160     {
6161       new_flags |= GDK_HINT_POS;
6162       hints_changed = TRUE;
6163     }
6164   
6165   /* Set hints if necessary
6166    */
6167   if (hints_changed)
6168     gdk_window_set_geometry_hints (widget->window,
6169                                    &new_geometry,
6170                                    new_flags);
6171   
6172   /* handle resizing/moving and widget tree allocation
6173    */
6174   if (window->configure_notify_received)
6175     { 
6176       GtkAllocation allocation;
6177
6178       /* If we have received a configure event since
6179        * the last time in this function, we need to
6180        * accept our new size and size_allocate child widgets.
6181        * (see gtk_window_configure_event() for more details).
6182        *
6183        * 1 or more configure notifies may have been received.
6184        * Also, configure_notify_received will only be TRUE
6185        * if all expected configure notifies have been received
6186        * (one per configure request), as an optimization.
6187        *
6188        */
6189       window->configure_notify_received = FALSE;
6190
6191       /* gtk_window_configure_event() filled in widget->allocation */
6192       allocation = widget->allocation;
6193       gtk_widget_size_allocate (widget, &allocation);
6194
6195       gdk_window_process_updates (widget->window, TRUE);
6196       
6197       gdk_window_configure_finished (widget->window);
6198
6199       /* If the configure request changed, it means that
6200        * we either:
6201        *   1) coincidentally changed hints or widget properties
6202        *      impacting the configure request before getting
6203        *      a configure notify, or
6204        *   2) some broken widget is changing its size request
6205        *      during size allocation, resulting in
6206        *      a false appearance of changed configure request.
6207        *
6208        * For 1), we could just go ahead and ask for the
6209        * new size right now, but doing that for 2)
6210        * might well be fighting the user (and can even
6211        * trigger a loop). Since we really don't want to
6212        * do that, we requeue a resize in hopes that
6213        * by the time it gets handled, the child has seen
6214        * the light and is willing to go along with the
6215        * new size. (this happens for the zvt widget, since
6216        * the size_allocate() above will have stored the
6217        * requisition corresponding to the new size in the
6218        * zvt widget)
6219        *
6220        * This doesn't buy us anything for 1), but it shouldn't
6221        * hurt us too badly, since it is what would have
6222        * happened if we had gotten the configure event before
6223        * the new size had been set.
6224        */
6225
6226       if (configure_request_size_changed ||
6227           configure_request_pos_changed)
6228         {
6229           /* Don't change the recorded last info after all, because we
6230            * haven't actually updated to the new info yet - we decided
6231            * to postpone our configure request until later.
6232            */
6233           info->last = saved_last_info;
6234           
6235           gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
6236         }
6237
6238       return;                   /* Bail out, we didn't really process the move/resize */
6239     }
6240   else if ((configure_request_size_changed || hints_changed) &&
6241            (widget->allocation.width != new_request.width ||
6242             widget->allocation.height != new_request.height))
6243
6244     {
6245       /* We are in one of the following situations:
6246        * A. configure_request_size_changed
6247        *    our requisition has changed and we need a different window size,
6248        *    so we request it from the window manager.
6249        * B. !configure_request_size_changed && hints_changed
6250        *    the window manager rejects our size, but we have just changed the
6251        *    window manager hints, so there's a chance our request will
6252        *    be honoured this time, so we try again.
6253        *
6254        * However, if the new requisition is the same as the current allocation,
6255        * we don't request it again, since we won't get a ConfigureNotify back from
6256        * the window manager unless it decides to change our requisition. If
6257        * we don't get the ConfigureNotify back, the resize queue will never be run.
6258        */
6259
6260       /* Now send the configure request */
6261       if (configure_request_pos_changed)
6262         {
6263           if (window->frame)
6264             {
6265               gdk_window_move_resize (window->frame,
6266                                       new_request.x - window->frame_left,
6267                                       new_request.y - window->frame_top,
6268                                       new_request.width + window->frame_left + window->frame_right,
6269                                       new_request.height + window->frame_top + window->frame_bottom);
6270               gdk_window_resize (widget->window,
6271                                  new_request.width, new_request.height);
6272             }
6273           else
6274             gdk_window_move_resize (widget->window,
6275                                     new_request.x, new_request.y,
6276                                     new_request.width, new_request.height);
6277         }
6278       else  /* only size changed */
6279         {
6280           if (window->frame)
6281             gdk_window_resize (window->frame,
6282                                new_request.width + window->frame_left + window->frame_right,
6283                                new_request.height + window->frame_top + window->frame_bottom);
6284           gdk_window_resize (widget->window,
6285                              new_request.width, new_request.height);
6286         }
6287       
6288       if (window->type == GTK_WINDOW_POPUP)
6289         {
6290           GtkAllocation allocation;
6291
6292           /* Directly size allocate for override redirect (popup) windows. */
6293           allocation.x = 0;
6294           allocation.y = 0;
6295           allocation.width = new_request.width;
6296           allocation.height = new_request.height;
6297
6298           gtk_widget_size_allocate (widget, &allocation);
6299
6300           gdk_window_process_updates (widget->window, TRUE);
6301
6302           if (container->resize_mode == GTK_RESIZE_QUEUE)
6303             gtk_widget_queue_draw (widget);
6304         }
6305       else
6306         {
6307           /* Increment the number of have-not-yet-received-notify requests */
6308           window->configure_request_count += 1;
6309           gdk_window_freeze_toplevel_updates_libgtk_only (widget->window);
6310
6311           /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
6312            * configure event in response to our resizing request.
6313            * the configure event will cause a new resize with
6314            * ->configure_notify_received=TRUE.
6315            * until then, we want to
6316            * - discard expose events
6317            * - coalesce resizes for our children
6318            * - defer any window resizes until the configure event arrived
6319            * to achieve this, we queue a resize for the window, but remove its
6320            * resizing handler, so resizing will not be handled from the next
6321            * idle handler but when the configure event arrives.
6322            *
6323            * FIXME: we should also dequeue the pending redraws here, since
6324            * we handle those ourselves upon ->configure_notify_received==TRUE.
6325            */
6326           if (container->resize_mode == GTK_RESIZE_QUEUE)
6327             {
6328               gtk_widget_queue_resize_no_redraw (widget);
6329               _gtk_container_dequeue_resize_handler (container);
6330             }
6331         }
6332     }
6333   else
6334     {
6335       /* Handle any position changes.
6336        */
6337       if (configure_request_pos_changed)
6338         {
6339           if (window->frame)
6340             {
6341               gdk_window_move (window->frame,
6342                                new_request.x - window->frame_left,
6343                                new_request.y - window->frame_top);
6344             }
6345           else
6346             gdk_window_move (widget->window,
6347                              new_request.x, new_request.y);
6348         }
6349
6350       /* And run the resize queue.
6351        */
6352       gtk_container_resize_children (container);
6353     }
6354   
6355   /* We have now processed a move/resize since the last position
6356    * constraint change, setting of the initial position, or resize.
6357    * (Not resetting these flags here can lead to infinite loops for
6358    * GTK_RESIZE_IMMEDIATE containers)
6359    */
6360   info->position_constraints_changed = FALSE;
6361   info->initial_pos_set = FALSE;
6362   info->resize_width = -1;
6363   info->resize_height = -1;
6364 }
6365
6366 /* Compare two sets of Geometry hints for equality.
6367  */
6368 static gboolean
6369 gtk_window_compare_hints (GdkGeometry *geometry_a,
6370                           guint        flags_a,
6371                           GdkGeometry *geometry_b,
6372                           guint        flags_b)
6373 {
6374   if (flags_a != flags_b)
6375     return FALSE;
6376   
6377   if ((flags_a & GDK_HINT_MIN_SIZE) &&
6378       (geometry_a->min_width != geometry_b->min_width ||
6379        geometry_a->min_height != geometry_b->min_height))
6380     return FALSE;
6381
6382   if ((flags_a & GDK_HINT_MAX_SIZE) &&
6383       (geometry_a->max_width != geometry_b->max_width ||
6384        geometry_a->max_height != geometry_b->max_height))
6385     return FALSE;
6386
6387   if ((flags_a & GDK_HINT_BASE_SIZE) &&
6388       (geometry_a->base_width != geometry_b->base_width ||
6389        geometry_a->base_height != geometry_b->base_height))
6390     return FALSE;
6391
6392   if ((flags_a & GDK_HINT_ASPECT) &&
6393       (geometry_a->min_aspect != geometry_b->min_aspect ||
6394        geometry_a->max_aspect != geometry_b->max_aspect))
6395     return FALSE;
6396
6397   if ((flags_a & GDK_HINT_RESIZE_INC) &&
6398       (geometry_a->width_inc != geometry_b->width_inc ||
6399        geometry_a->height_inc != geometry_b->height_inc))
6400     return FALSE;
6401
6402   if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
6403       geometry_a->win_gravity != geometry_b->win_gravity)
6404     return FALSE;
6405
6406   return TRUE;
6407 }
6408
6409 void
6410 _gtk_window_constrain_size (GtkWindow   *window,
6411                             gint         width,
6412                             gint         height,
6413                             gint        *new_width,
6414                             gint        *new_height)
6415 {
6416   GtkWindowGeometryInfo *info;
6417
6418   g_return_if_fail (GTK_IS_WINDOW (window));
6419
6420   info = window->geometry_info;
6421   if (info)
6422     {
6423       GdkWindowHints flags = info->last.flags;
6424       GdkGeometry *geometry = &info->last.geometry;
6425       
6426       gtk_window_constrain_size (window,
6427                                  geometry,
6428                                  flags,
6429                                  width,
6430                                  height,
6431                                  new_width,
6432                                  new_height);
6433     }
6434 }
6435
6436 static void 
6437 gtk_window_constrain_size (GtkWindow   *window,
6438                            GdkGeometry *geometry,
6439                            guint        flags,
6440                            gint         width,
6441                            gint         height,
6442                            gint        *new_width,
6443                            gint        *new_height)
6444 {
6445   gdk_window_constrain_size (geometry, flags, width, height,
6446                              new_width, new_height);
6447 }
6448
6449 /* Compute the set of geometry hints and flags for a window
6450  * based on the application set geometry, and requisiition
6451  * of the window. gtk_widget_size_request() must have been
6452  * called first.
6453  */
6454 static void
6455 gtk_window_compute_hints (GtkWindow   *window,
6456                           GdkGeometry *new_geometry,
6457                           guint       *new_flags)
6458 {
6459   GtkWidget *widget;
6460   gint extra_width = 0;
6461   gint extra_height = 0;
6462   GtkWindowGeometryInfo *geometry_info;
6463   GtkRequisition requisition;
6464
6465   widget = GTK_WIDGET (window);
6466   
6467   gtk_widget_get_child_requisition (widget, &requisition);
6468   geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
6469
6470   if (geometry_info)
6471     {
6472       *new_flags = geometry_info->mask;
6473       *new_geometry = geometry_info->geometry;
6474     }
6475   else
6476     {
6477       *new_flags = 0;
6478     }
6479   
6480   if (geometry_info && geometry_info->widget)
6481     {
6482       GtkRequisition child_requisition;
6483
6484       /* FIXME: This really isn't right. It gets the min size wrong and forces
6485        * callers to do horrible hacks like set a huge usize on the child requisition
6486        * to get the base size right. We really want to find the answers to:
6487        *
6488        *  - If the geometry widget was infinitely big, how much extra space
6489        *    would be needed for the stuff around it.
6490        *
6491        *  - If the geometry widget was infinitely small, how big would the
6492        *    window still have to be.
6493        *
6494        * Finding these answers would be a bit of a mess here. (Bug #68668)
6495        */
6496       gtk_widget_get_child_requisition (geometry_info->widget, &child_requisition);
6497       
6498       extra_width = widget->requisition.width - child_requisition.width;
6499       extra_height = widget->requisition.height - child_requisition.height;
6500     }
6501
6502   /* We don't want to set GDK_HINT_POS in here, we just set it
6503    * in gtk_window_move_resize() when we want the position
6504    * honored.
6505    */
6506   
6507   if (*new_flags & GDK_HINT_BASE_SIZE)
6508     {
6509       new_geometry->base_width += extra_width;
6510       new_geometry->base_height += extra_height;
6511     }
6512   else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
6513            (*new_flags & GDK_HINT_RESIZE_INC) &&
6514            ((extra_width != 0) || (extra_height != 0)))
6515     {
6516       *new_flags |= GDK_HINT_BASE_SIZE;
6517       
6518       new_geometry->base_width = extra_width;
6519       new_geometry->base_height = extra_height;
6520     }
6521   
6522   if (*new_flags & GDK_HINT_MIN_SIZE)
6523     {
6524       if (new_geometry->min_width < 0)
6525         new_geometry->min_width = requisition.width;
6526       else
6527         new_geometry->min_width += extra_width;
6528
6529       if (new_geometry->min_height < 0)
6530         new_geometry->min_height = requisition.height;
6531       else
6532         new_geometry->min_height += extra_height;
6533     }
6534   else if (!window->allow_shrink)
6535     {
6536       *new_flags |= GDK_HINT_MIN_SIZE;
6537       
6538       new_geometry->min_width = requisition.width;
6539       new_geometry->min_height = requisition.height;
6540     }
6541   
6542   if (*new_flags & GDK_HINT_MAX_SIZE)
6543     {
6544       if (new_geometry->max_width < 0)
6545         new_geometry->max_width = requisition.width;
6546       else
6547         new_geometry->max_width += extra_width;
6548
6549       if (new_geometry->max_height < 0)
6550         new_geometry->max_height = requisition.height;
6551       else
6552         new_geometry->max_height += extra_height;
6553     }
6554   else if (!window->allow_grow)
6555     {
6556       *new_flags |= GDK_HINT_MAX_SIZE;
6557       
6558       new_geometry->max_width = requisition.width;
6559       new_geometry->max_height = requisition.height;
6560     }
6561
6562   *new_flags |= GDK_HINT_WIN_GRAVITY;
6563   new_geometry->win_gravity = window->gravity;
6564 }
6565
6566 /***********************
6567  * Redrawing functions *
6568  ***********************/
6569
6570 static void
6571 gtk_window_paint (GtkWidget     *widget,
6572                   GdkRectangle *area)
6573 {
6574   gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL, 
6575                       GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
6576 }
6577
6578 static gint
6579 gtk_window_expose (GtkWidget      *widget,
6580                    GdkEventExpose *event)
6581 {
6582   if (!GTK_WIDGET_APP_PAINTABLE (widget))
6583     gtk_window_paint (widget, &event->area);
6584   
6585   if (GTK_WIDGET_CLASS (gtk_window_parent_class)->expose_event)
6586     return GTK_WIDGET_CLASS (gtk_window_parent_class)->expose_event (widget, event);
6587
6588   return FALSE;
6589 }
6590
6591 /**
6592  * gtk_window_set_has_frame:
6593  * @window: a #GtkWindow
6594  * @setting: a boolean
6595  *
6596  * (Note: this is a special-purpose function for the framebuffer port,
6597  *  that causes GTK+ to draw its own window border. For most applications,
6598  *  you want gtk_window_set_decorated() instead, which tells the window
6599  *  manager whether to draw the window border.)
6600  * 
6601  * If this function is called on a window with setting of %TRUE, before
6602  * it is realized or showed, it will have a "frame" window around
6603  * @window->window, accessible in @window->frame. Using the signal 
6604  * frame_event you can receive all events targeted at the frame.
6605  * 
6606  * This function is used by the linux-fb port to implement managed
6607  * windows, but it could conceivably be used by X-programs that
6608  * want to do their own window decorations.
6609  *
6610  **/
6611 void
6612 gtk_window_set_has_frame (GtkWindow *window, 
6613                           gboolean   setting)
6614 {
6615   g_return_if_fail (GTK_IS_WINDOW (window));
6616   g_return_if_fail (!GTK_WIDGET_REALIZED (window));
6617
6618   window->has_frame = setting != FALSE;
6619 }
6620
6621 /**
6622  * gtk_window_get_has_frame:
6623  * @window: a #GtkWindow
6624  * 
6625  * Accessor for whether the window has a frame window exterior to
6626  * @window->window. Gets the value set by gtk_window_set_has_frame ().
6627  *
6628  * Return value: %TRUE if a frame has been added to the window
6629  *   via gtk_window_set_has_frame().
6630  **/
6631 gboolean
6632 gtk_window_get_has_frame (GtkWindow *window)
6633 {
6634   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6635
6636   return window->has_frame;
6637 }
6638
6639 /**
6640  * gtk_window_set_frame_dimensions:
6641  * @window: a #GtkWindow that has a frame
6642  * @left: The width of the left border
6643  * @top: The height of the top border
6644  * @right: The width of the right border
6645  * @bottom: The height of the bottom border
6646  *
6647  * (Note: this is a special-purpose function intended for the framebuffer
6648  *  port; see gtk_window_set_has_frame(). It will have no effect on the
6649  *  window border drawn by the window manager, which is the normal
6650  *  case when using the X Window system.)
6651  *
6652  * For windows with frames (see gtk_window_set_has_frame()) this function
6653  * can be used to change the size of the frame border.
6654  **/
6655 void
6656 gtk_window_set_frame_dimensions (GtkWindow *window, 
6657                                  gint       left,
6658                                  gint       top,
6659                                  gint       right,
6660                                  gint       bottom)
6661 {
6662   GtkWidget *widget;
6663
6664   g_return_if_fail (GTK_IS_WINDOW (window));
6665
6666   widget = GTK_WIDGET (window);
6667
6668   if (window->frame_left == left &&
6669       window->frame_top == top &&
6670       window->frame_right == right && 
6671       window->frame_bottom == bottom)
6672     return;
6673
6674   window->frame_left = left;
6675   window->frame_top = top;
6676   window->frame_right = right;
6677   window->frame_bottom = bottom;
6678
6679   if (GTK_WIDGET_REALIZED (widget) && window->frame)
6680     {
6681       gint width = widget->allocation.width + left + right;
6682       gint height = widget->allocation.height + top + bottom;
6683       gdk_window_resize (window->frame, width, height);
6684       gtk_decorated_window_move_resize_window (window,
6685                                                left, top,
6686                                                widget->allocation.width,
6687                                                widget->allocation.height);
6688     }
6689 }
6690
6691 /**
6692  * gtk_window_present:
6693  * @window: a #GtkWindow
6694  *
6695  * Presents a window to the user. This may mean raising the window
6696  * in the stacking order, deiconifying it, moving it to the current
6697  * desktop, and/or giving it the keyboard focus, possibly dependent
6698  * on the user's platform, window manager, and preferences.
6699  *
6700  * If @window is hidden, this function calls gtk_widget_show()
6701  * as well.
6702  * 
6703  * This function should be used when the user tries to open a window
6704  * that's already open. Say for example the preferences dialog is
6705  * currently open, and the user chooses Preferences from the menu
6706  * a second time; use gtk_window_present() to move the already-open dialog
6707  * where the user can see it.
6708  *
6709  * If you are calling this function in response to a user interaction,
6710  * it is preferable to use gtk_window_present_with_time().
6711  * 
6712  **/
6713 void
6714 gtk_window_present (GtkWindow *window)
6715 {
6716   gtk_window_present_with_time (window, GDK_CURRENT_TIME);
6717 }
6718
6719 /**
6720  * gtk_window_present_with_time:
6721  * @window: a #GtkWindow
6722  * @timestamp: the timestamp of the user interaction (typically a 
6723  *   button or key press event) which triggered this call
6724  *
6725  * Presents a window to the user in response to a user interaction.
6726  * If you need to present a window without a timestamp, use 
6727  * gtk_window_present(). See gtk_window_present() for details. 
6728  * 
6729  * Since: 2.8
6730  **/
6731 void
6732 gtk_window_present_with_time (GtkWindow *window,
6733                               guint32    timestamp)
6734 {
6735   GtkWidget *widget;
6736
6737   g_return_if_fail (GTK_IS_WINDOW (window));
6738
6739   widget = GTK_WIDGET (window);
6740
6741   if (GTK_WIDGET_VISIBLE (window))
6742     {
6743       g_assert (widget->window != NULL);
6744       
6745       gdk_window_show (widget->window);
6746
6747       /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
6748       if (timestamp == GDK_CURRENT_TIME)
6749         {
6750 #ifdef GDK_WINDOWING_X11
6751           GdkDisplay *display;
6752
6753           display = gtk_widget_get_display (GTK_WIDGET (window));
6754           timestamp = gdk_x11_display_get_user_time (display);
6755 #else
6756           timestamp = gtk_get_current_event_time ();
6757 #endif
6758         }
6759
6760       gdk_window_focus (widget->window, timestamp);
6761     }
6762   else
6763     {
6764       gtk_widget_show (widget);
6765     }
6766 }
6767
6768 /**
6769  * gtk_window_iconify:
6770  * @window: a #GtkWindow
6771  *
6772  * Asks to iconify (i.e. minimize) the specified @window. Note that
6773  * you shouldn't assume the window is definitely iconified afterward,
6774  * because other entities (e.g. the user or <link
6775  * linkend="gtk-X11-arch">window manager</link>) could deiconify it
6776  * again, or there may not be a window manager in which case
6777  * iconification isn't possible, etc. But normally the window will end
6778  * up iconified. Just don't write code that crashes if not.
6779  *
6780  * It's permitted to call this function before showing a window,
6781  * in which case the window will be iconified before it ever appears
6782  * onscreen.
6783  *
6784  * You can track iconification via the "window-state-event" signal
6785  * on #GtkWidget.
6786  * 
6787  **/
6788 void
6789 gtk_window_iconify (GtkWindow *window)
6790 {
6791   GtkWidget *widget;
6792   GdkWindow *toplevel;
6793   
6794   g_return_if_fail (GTK_IS_WINDOW (window));
6795
6796   widget = GTK_WIDGET (window);
6797
6798   window->iconify_initially = TRUE;
6799
6800   if (window->frame)
6801     toplevel = window->frame;
6802   else
6803     toplevel = widget->window;
6804   
6805   if (toplevel != NULL)
6806     gdk_window_iconify (toplevel);
6807 }
6808
6809 /**
6810  * gtk_window_deiconify:
6811  * @window: a #GtkWindow
6812  *
6813  * Asks to deiconify (i.e. unminimize) the specified @window. Note
6814  * that you shouldn't assume the window is definitely deiconified
6815  * afterward, because other entities (e.g. the user or <link
6816  * linkend="gtk-X11-arch">window manager</link>) could iconify it
6817  * again before your code which assumes deiconification gets to run.
6818  *
6819  * You can track iconification via the "window-state-event" signal
6820  * on #GtkWidget.
6821  **/
6822 void
6823 gtk_window_deiconify (GtkWindow *window)
6824 {
6825   GtkWidget *widget;
6826   GdkWindow *toplevel;
6827   
6828   g_return_if_fail (GTK_IS_WINDOW (window));
6829
6830   widget = GTK_WIDGET (window);
6831
6832   window->iconify_initially = FALSE;
6833
6834   if (window->frame)
6835     toplevel = window->frame;
6836   else
6837     toplevel = widget->window;
6838   
6839   if (toplevel != NULL)
6840     gdk_window_deiconify (toplevel);
6841 }
6842
6843 /**
6844  * gtk_window_stick:
6845  * @window: a #GtkWindow
6846  *
6847  * Asks to stick @window, which means that it will appear on all user
6848  * desktops. Note that you shouldn't assume the window is definitely
6849  * stuck afterward, because other entities (e.g. the user or <link
6850  * linkend="gtk-X11-arch">window manager</link>) could unstick it
6851  * again, and some window managers do not support sticking
6852  * windows. But normally the window will end up stuck. Just don't
6853  * write code that crashes if not.
6854  *
6855  * It's permitted to call this function before showing a window.
6856  *
6857  * You can track stickiness via the "window-state-event" signal
6858  * on #GtkWidget.
6859  * 
6860  **/
6861 void
6862 gtk_window_stick (GtkWindow *window)
6863 {
6864   GtkWidget *widget;
6865   GdkWindow *toplevel;
6866   
6867   g_return_if_fail (GTK_IS_WINDOW (window));
6868
6869   widget = GTK_WIDGET (window);
6870
6871   window->stick_initially = TRUE;
6872
6873   if (window->frame)
6874     toplevel = window->frame;
6875   else
6876     toplevel = widget->window;
6877   
6878   if (toplevel != NULL)
6879     gdk_window_stick (toplevel);
6880 }
6881
6882 /**
6883  * gtk_window_unstick:
6884  * @window: a #GtkWindow
6885  *
6886  * Asks to unstick @window, which means that it will appear on only
6887  * one of the user's desktops. Note that you shouldn't assume the
6888  * window is definitely unstuck afterward, because other entities
6889  * (e.g. the user or <link linkend="gtk-X11-arch">window
6890  * manager</link>) could stick it again. But normally the window will
6891  * end up stuck. Just don't write code that crashes if not.
6892  *
6893  * You can track stickiness via the "window-state-event" signal
6894  * on #GtkWidget.
6895  * 
6896  **/
6897 void
6898 gtk_window_unstick (GtkWindow *window)
6899 {
6900   GtkWidget *widget;
6901   GdkWindow *toplevel;
6902   
6903   g_return_if_fail (GTK_IS_WINDOW (window));
6904
6905   widget = GTK_WIDGET (window);
6906
6907   window->stick_initially = FALSE;
6908
6909   if (window->frame)
6910     toplevel = window->frame;
6911   else
6912     toplevel = widget->window;
6913   
6914   if (toplevel != NULL)
6915     gdk_window_unstick (toplevel);
6916 }
6917
6918 /**
6919  * gtk_window_maximize:
6920  * @window: a #GtkWindow
6921  *
6922  * Asks to maximize @window, so that it becomes full-screen. Note that
6923  * you shouldn't assume the window is definitely maximized afterward,
6924  * because other entities (e.g. the user or <link
6925  * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
6926  * again, and not all window managers support maximization. But
6927  * normally the window will end up maximized. Just don't write code
6928  * that crashes if not.
6929  *
6930  * It's permitted to call this function before showing a window,
6931  * in which case the window will be maximized when it appears onscreen
6932  * initially.
6933  *
6934  * You can track maximization via the "window-state-event" signal
6935  * on #GtkWidget.
6936  * 
6937  **/
6938 void
6939 gtk_window_maximize (GtkWindow *window)
6940 {
6941   GtkWidget *widget;
6942   GdkWindow *toplevel;
6943   
6944   g_return_if_fail (GTK_IS_WINDOW (window));
6945
6946   widget = GTK_WIDGET (window);
6947
6948   window->maximize_initially = TRUE;
6949
6950   if (window->frame)
6951     toplevel = window->frame;
6952   else
6953     toplevel = widget->window;
6954   
6955   if (toplevel != NULL)
6956     gdk_window_maximize (toplevel);
6957 }
6958
6959 /**
6960  * gtk_window_unmaximize:
6961  * @window: a #GtkWindow
6962  *
6963  * Asks to unmaximize @window. Note that you shouldn't assume the
6964  * window is definitely unmaximized afterward, because other entities
6965  * (e.g. the user or <link linkend="gtk-X11-arch">window
6966  * manager</link>) could maximize it again, and not all window
6967  * managers honor requests to unmaximize. But normally the window will
6968  * end up unmaximized. Just don't write code that crashes if not.
6969  *
6970  * You can track maximization via the "window-state-event" signal
6971  * on #GtkWidget.
6972  * 
6973  **/
6974 void
6975 gtk_window_unmaximize (GtkWindow *window)
6976 {
6977   GtkWidget *widget;
6978   GdkWindow *toplevel;
6979   
6980   g_return_if_fail (GTK_IS_WINDOW (window));
6981
6982   widget = GTK_WIDGET (window);
6983
6984   window->maximize_initially = FALSE;
6985
6986   if (window->frame)
6987     toplevel = window->frame;
6988   else
6989     toplevel = widget->window;
6990   
6991   if (toplevel != NULL)
6992     gdk_window_unmaximize (toplevel);
6993 }
6994
6995 /**
6996  * gtk_window_fullscreen:
6997  * @window: a #GtkWindow
6998  *
6999  * Asks to place @window in the fullscreen state. Note that you
7000  * shouldn't assume the window is definitely full screen afterward,
7001  * because other entities (e.g. the user or <link
7002  * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7003  * again, and not all window managers honor requests to fullscreen
7004  * windows. But normally the window will end up fullscreen. Just
7005  * don't write code that crashes if not.
7006  *
7007  * You can track the fullscreen state via the "window-state-event" signal
7008  * on #GtkWidget.
7009  * 
7010  * Since: 2.2
7011  **/
7012 void
7013 gtk_window_fullscreen (GtkWindow *window)
7014 {
7015   GtkWidget *widget;
7016   GdkWindow *toplevel;
7017   GtkWindowPrivate *priv;
7018   
7019   g_return_if_fail (GTK_IS_WINDOW (window));
7020
7021   widget = GTK_WIDGET (window);
7022   priv = GTK_WINDOW_GET_PRIVATE (window);
7023   
7024   priv->fullscreen_initially = TRUE;
7025
7026   if (window->frame)
7027     toplevel = window->frame;
7028   else
7029     toplevel = widget->window;
7030   
7031   if (toplevel != NULL)
7032     gdk_window_fullscreen (toplevel);
7033 }
7034
7035 /**
7036  * gtk_window_unfullscreen:
7037  * @window: a #GtkWindow
7038  *
7039  * Asks to toggle off the fullscreen state for @window. Note that you
7040  * shouldn't assume the window is definitely not full screen
7041  * afterward, because other entities (e.g. the user or <link
7042  * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7043  * again, and not all window managers honor requests to unfullscreen
7044  * windows. But normally the window will end up restored to its normal
7045  * state. Just don't write code that crashes if not.
7046  *
7047  * You can track the fullscreen state via the "window-state-event" signal
7048  * on #GtkWidget.
7049  * 
7050  * Since: 2.2
7051  **/
7052 void
7053 gtk_window_unfullscreen (GtkWindow *window)
7054 {
7055   GtkWidget *widget;
7056   GdkWindow *toplevel;
7057   GtkWindowPrivate *priv;
7058   
7059   g_return_if_fail (GTK_IS_WINDOW (window));
7060
7061   widget = GTK_WIDGET (window);
7062   priv = GTK_WINDOW_GET_PRIVATE (window);
7063   
7064   priv->fullscreen_initially = FALSE;
7065
7066   if (window->frame)
7067     toplevel = window->frame;
7068   else
7069     toplevel = widget->window;
7070   
7071   if (toplevel != NULL)
7072     gdk_window_unfullscreen (toplevel);
7073 }
7074
7075 /**
7076  * gtk_window_set_keep_above:
7077  * @window: a #GtkWindow
7078  * @setting: whether to keep @window above other windows
7079  *
7080  * Asks to keep @window above, so that it stays on top. Note that
7081  * you shouldn't assume the window is definitely above afterward,
7082  * because other entities (e.g. the user or <link
7083  * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
7084  * and not all window managers support keeping windows above. But
7085  * normally the window will end kept above. Just don't write code
7086  * that crashes if not.
7087  *
7088  * It's permitted to call this function before showing a window,
7089  * in which case the window will be kept above when it appears onscreen
7090  * initially.
7091  *
7092  * You can track the above state via the "window-state-event" signal
7093  * on #GtkWidget.
7094  *
7095  * Note that, according to the <ulink 
7096  * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window 
7097  * Manager Hints</ulink> specification, the above state is mainly meant 
7098  * for user preferences and should not be used by applications e.g. for 
7099  * drawing attention to their dialogs.
7100  *
7101  * Since: 2.4
7102  **/
7103 void
7104 gtk_window_set_keep_above (GtkWindow *window,
7105                            gboolean   setting)
7106 {
7107   GtkWidget *widget;
7108   GtkWindowPrivate *priv;
7109   GdkWindow *toplevel;
7110
7111   g_return_if_fail (GTK_IS_WINDOW (window));
7112
7113   widget = GTK_WIDGET (window);
7114   priv = GTK_WINDOW_GET_PRIVATE (window);
7115
7116   priv->above_initially = setting != FALSE;
7117   if (setting)
7118     priv->below_initially = FALSE;
7119
7120   if (window->frame)
7121     toplevel = window->frame;
7122   else
7123     toplevel = widget->window;
7124
7125   if (toplevel != NULL)
7126     gdk_window_set_keep_above (toplevel, setting);
7127 }
7128
7129 /**
7130  * gtk_window_set_keep_below:
7131  * @window: a #GtkWindow
7132  * @setting: whether to keep @window below other windows
7133  *
7134  * Asks to keep @window below, so that it stays in bottom. Note that
7135  * you shouldn't assume the window is definitely below afterward,
7136  * because other entities (e.g. the user or <link
7137  * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
7138  * and not all window managers support putting windows below. But
7139  * normally the window will be kept below. Just don't write code
7140  * that crashes if not.
7141  *
7142  * It's permitted to call this function before showing a window,
7143  * in which case the window will be kept below when it appears onscreen
7144  * initially.
7145  *
7146  * You can track the below state via the "window-state-event" signal
7147  * on #GtkWidget.
7148  *
7149  * Note that, according to the <ulink 
7150  * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window 
7151  * Manager Hints</ulink> specification, the above state is mainly meant 
7152  * for user preferences and should not be used by applications e.g. for 
7153  * drawing attention to their dialogs.
7154  *
7155  * Since: 2.4
7156  **/
7157 void
7158 gtk_window_set_keep_below (GtkWindow *window,
7159                            gboolean   setting)
7160 {
7161   GtkWidget *widget;
7162   GtkWindowPrivate *priv;
7163   GdkWindow *toplevel;
7164
7165   g_return_if_fail (GTK_IS_WINDOW (window));
7166
7167   widget = GTK_WIDGET (window);
7168   priv = GTK_WINDOW_GET_PRIVATE (window);
7169
7170   priv->below_initially = setting != FALSE;
7171   if (setting)
7172     priv->above_initially = FALSE;
7173
7174   if (window->frame)
7175     toplevel = window->frame;
7176   else
7177     toplevel = widget->window;
7178
7179   if (toplevel != NULL)
7180     gdk_window_set_keep_below (toplevel, setting);
7181 }
7182
7183 /**
7184  * gtk_window_set_resizable:
7185  * @window: a #GtkWindow
7186  * @resizable: %TRUE if the user can resize this window
7187  *
7188  * Sets whether the user can resize a window. Windows are user resizable
7189  * by default.
7190  **/
7191 void
7192 gtk_window_set_resizable (GtkWindow *window,
7193                           gboolean   resizable)
7194 {
7195   g_return_if_fail (GTK_IS_WINDOW (window));
7196
7197   gtk_window_set_policy_internal (window, FALSE, resizable, FALSE);
7198 }
7199
7200 /**
7201  * gtk_window_get_resizable:
7202  * @window: a #GtkWindow
7203  *
7204  * Gets the value set by gtk_window_set_resizable().
7205  *
7206  * Return value: %TRUE if the user can resize the window
7207  **/
7208 gboolean
7209 gtk_window_get_resizable (GtkWindow *window)
7210 {
7211   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7212
7213   /* allow_grow is most likely to indicate the semantic concept we
7214    * mean by "resizable" (and will be a reliable indicator if
7215    * set_policy() hasn't been called)
7216    */
7217   return window->allow_grow;
7218 }
7219
7220 /**
7221  * gtk_window_set_gravity:
7222  * @window: a #GtkWindow
7223  * @gravity: window gravity
7224  *
7225  * Window gravity defines the meaning of coordinates passed to
7226  * gtk_window_move(). See gtk_window_move() and #GdkGravity for
7227  * more details.
7228  *
7229  * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
7230  * typically "do what you mean."
7231  *
7232  **/
7233 void
7234 gtk_window_set_gravity (GtkWindow *window,
7235                         GdkGravity gravity)
7236 {
7237   g_return_if_fail (GTK_IS_WINDOW (window));
7238
7239   if (gravity != window->gravity)
7240     {
7241       window->gravity = gravity;
7242
7243       /* gtk_window_move_resize() will adapt gravity
7244        */
7245       gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7246
7247       g_object_notify (G_OBJECT (window), "gravity");
7248     }
7249 }
7250
7251 /**
7252  * gtk_window_get_gravity:
7253  * @window: a #GtkWindow
7254  *
7255  * Gets the value set by gtk_window_set_gravity().
7256  *
7257  * Return value: window gravity
7258  **/
7259 GdkGravity
7260 gtk_window_get_gravity (GtkWindow *window)
7261 {
7262   g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
7263
7264   return window->gravity;
7265 }
7266
7267 /**
7268  * gtk_window_begin_resize_drag:
7269  * @window: a #GtkWindow
7270  * @button: mouse button that initiated the drag
7271  * @edge: position of the resize control
7272  * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7273  * @root_y: Y position where the user clicked to initiate the drag
7274  * @timestamp: timestamp from the click event that initiated the drag
7275  *
7276  * Starts resizing a window. This function is used if an application
7277  * has window resizing controls. When GDK can support it, the resize
7278  * will be done using the standard mechanism for the <link
7279  * linkend="gtk-X11-arch">window manager</link> or windowing
7280  * system. Otherwise, GDK will try to emulate window resizing,
7281  * potentially not all that well, depending on the windowing system.
7282  * 
7283  **/
7284 void
7285 gtk_window_begin_resize_drag  (GtkWindow    *window,
7286                                GdkWindowEdge edge,
7287                                gint          button,
7288                                gint          root_x,
7289                                gint          root_y,
7290                                guint32       timestamp)
7291 {
7292   GtkWidget *widget;
7293   GdkWindow *toplevel;
7294   
7295   g_return_if_fail (GTK_IS_WINDOW (window));
7296   g_return_if_fail (GTK_WIDGET_VISIBLE (window));
7297   
7298   widget = GTK_WIDGET (window);
7299   
7300   if (window->frame)
7301     toplevel = window->frame;
7302   else
7303     toplevel = widget->window;
7304   
7305   gdk_window_begin_resize_drag (toplevel,
7306                                 edge, button,
7307                                 root_x, root_y,
7308                                 timestamp);
7309 }
7310
7311 /**
7312  * gtk_window_get_frame_dimensions:
7313  * @window: a #GtkWindow
7314  * @left: location to store the width of the frame at the left, or %NULL
7315  * @top: location to store the height of the frame at the top, or %NULL
7316  * @right: location to store the width of the frame at the returns, or %NULL
7317  * @bottom: location to store the height of the frame at the bottom, or %NULL
7318  *
7319  * (Note: this is a special-purpose function intended for the
7320  *  framebuffer port; see gtk_window_set_has_frame(). It will not
7321  *  return the size of the window border drawn by the <link
7322  *  linkend="gtk-X11-arch">window manager</link>, which is the normal
7323  *  case when using a windowing system.  See
7324  *  gdk_window_get_frame_extents() to get the standard window border
7325  *  extents.)
7326  * 
7327  * Retrieves the dimensions of the frame window for this toplevel.
7328  * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
7329  **/
7330 void
7331 gtk_window_get_frame_dimensions (GtkWindow *window,
7332                                  gint      *left,
7333                                  gint      *top,
7334                                  gint      *right,
7335                                  gint      *bottom)
7336 {
7337   g_return_if_fail (GTK_IS_WINDOW (window));
7338
7339   if (left)
7340     *left = window->frame_left;
7341   if (top)
7342     *top = window->frame_top;
7343   if (right)
7344     *right = window->frame_right;
7345   if (bottom)
7346     *bottom = window->frame_bottom;
7347 }
7348
7349 /**
7350  * gtk_window_begin_move_drag:
7351  * @window: a #GtkWindow
7352  * @button: mouse button that initiated the drag
7353  * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7354  * @root_y: Y position where the user clicked to initiate the drag
7355  * @timestamp: timestamp from the click event that initiated the drag
7356  *
7357  * Starts moving a window. This function is used if an application has
7358  * window movement grips. When GDK can support it, the window movement
7359  * will be done using the standard mechanism for the <link
7360  * linkend="gtk-X11-arch">window manager</link> or windowing
7361  * system. Otherwise, GDK will try to emulate window movement,
7362  * potentially not all that well, depending on the windowing system.
7363  * 
7364  **/
7365 void
7366 gtk_window_begin_move_drag  (GtkWindow *window,
7367                              gint       button,
7368                              gint       root_x,
7369                              gint       root_y,
7370                              guint32    timestamp)
7371 {
7372   GtkWidget *widget;
7373   GdkWindow *toplevel;
7374   
7375   g_return_if_fail (GTK_IS_WINDOW (window));
7376   g_return_if_fail (GTK_WIDGET_VISIBLE (window));
7377   
7378   widget = GTK_WIDGET (window);
7379   
7380   if (window->frame)
7381     toplevel = window->frame;
7382   else
7383     toplevel = widget->window;
7384   
7385   gdk_window_begin_move_drag (toplevel,
7386                               button,
7387                               root_x, root_y,
7388                               timestamp);
7389 }
7390
7391 /** 
7392  * gtk_window_set_screen:
7393  * @window: a #GtkWindow.
7394  * @screen: a #GdkScreen.
7395  *
7396  * Sets the #GdkScreen where the @window is displayed; if
7397  * the window is already mapped, it will be unmapped, and
7398  * then remapped on the new screen.
7399  *
7400  * Since: 2.2
7401  */
7402 void
7403 gtk_window_set_screen (GtkWindow *window,
7404                        GdkScreen *screen)
7405 {
7406   GtkWidget *widget;
7407   GdkScreen *previous_screen;
7408   gboolean was_mapped;
7409   
7410   g_return_if_fail (GTK_IS_WINDOW (window));
7411   g_return_if_fail (GDK_IS_SCREEN (screen));
7412
7413   if (screen == window->screen)
7414     return;
7415
7416   widget = GTK_WIDGET (window);
7417
7418   previous_screen = window->screen;
7419   was_mapped = GTK_WIDGET_MAPPED (widget);
7420
7421   if (was_mapped)
7422     gtk_widget_unmap (widget);
7423   if (GTK_WIDGET_REALIZED (widget))
7424     gtk_widget_unrealize (widget);
7425       
7426   gtk_window_free_key_hash (window);
7427   window->screen = screen;
7428   gtk_widget_reset_rc_styles (widget);
7429   if (screen != previous_screen)
7430     {
7431       g_signal_handlers_disconnect_by_func (previous_screen,
7432                                             gtk_window_on_composited_changed, window);
7433       g_signal_connect (screen, "composited-changed", 
7434                         G_CALLBACK (gtk_window_on_composited_changed), window);
7435       
7436       _gtk_widget_propagate_screen_changed (widget, previous_screen);
7437       _gtk_widget_propagate_composited_changed (widget);
7438     }
7439   g_object_notify (G_OBJECT (window), "screen");
7440
7441   if (was_mapped)
7442     gtk_widget_map (widget);
7443 }
7444
7445 static void
7446 gtk_window_on_composited_changed (GdkScreen *screen,
7447                                   GtkWindow *window)
7448 {
7449   gtk_widget_queue_draw (GTK_WIDGET (window));
7450   
7451   _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
7452 }
7453
7454 static GdkScreen *
7455 gtk_window_check_screen (GtkWindow *window)
7456 {
7457   if (window->screen)
7458     return window->screen;
7459   else
7460     {
7461       g_warning ("Screen for GtkWindow not set; you must always set\n"
7462                  "a screen for a GtkWindow before using the window");
7463       return NULL;
7464     }
7465 }
7466
7467 /** 
7468  * gtk_window_get_screen:
7469  * @window: a #GtkWindow.
7470  *
7471  * Returns the #GdkScreen associated with @window.
7472  *
7473  * Return value: a #GdkScreen.
7474  *
7475  * Since: 2.2
7476  */
7477 GdkScreen*
7478 gtk_window_get_screen (GtkWindow *window)
7479 {
7480   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
7481    
7482   return window->screen;
7483 }
7484
7485 /**
7486  * gtk_window_is_active:
7487  * @window: a #GtkWindow
7488  * 
7489  * Returns whether the window is part of the current active toplevel.
7490  * (That is, the toplevel window receiving keystrokes.)
7491  * The return value is %TRUE if the window is active toplevel
7492  * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
7493  * You might use this function if you wanted to draw a widget
7494  * differently in an active window from a widget in an inactive window.
7495  * See gtk_window_has_toplevel_focus()
7496  * 
7497  * Return value: %TRUE if the window part of the current active window.
7498  *
7499  * Since: 2.4
7500  **/
7501 gboolean
7502 gtk_window_is_active (GtkWindow *window)
7503 {
7504   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7505
7506   return window->is_active;
7507 }
7508
7509 /**
7510  * gtk_window_has_toplevel_focus:
7511  * @window: a #GtkWindow
7512  * 
7513  * Returns whether the input focus is within this GtkWindow.
7514  * For real toplevel windows, this is identical to gtk_window_is_active(),
7515  * but for embedded windows, like #GtkPlug, the results will differ.
7516  * 
7517  * Return value: %TRUE if the input focus is within this GtkWindow
7518  *
7519  * Since: 2.4
7520  **/
7521 gboolean
7522 gtk_window_has_toplevel_focus (GtkWindow *window)
7523 {
7524   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7525
7526   return window->has_toplevel_focus;
7527 }
7528
7529 static void
7530 gtk_window_group_class_init (GtkWindowGroupClass *klass)
7531 {
7532 }
7533
7534 GType
7535 gtk_window_group_get_type (void)
7536 {
7537   static GType window_group_type = 0;
7538
7539   if (!window_group_type)
7540     {
7541       const GTypeInfo window_group_info =
7542       {
7543         sizeof (GtkWindowGroupClass),
7544         NULL,           /* base_init */
7545         NULL,           /* base_finalize */
7546         (GClassInitFunc) gtk_window_group_class_init,
7547         NULL,           /* class_finalize */
7548         NULL,           /* class_data */
7549         sizeof (GtkWindowGroup),
7550         0,              /* n_preallocs */
7551         (GInstanceInitFunc) NULL,
7552       };
7553
7554       window_group_type = g_type_register_static (G_TYPE_OBJECT, I_("GtkWindowGroup"), 
7555                                                   &window_group_info, 0);
7556     }
7557
7558   return window_group_type;
7559 }
7560
7561 /**
7562  * gtk_window_group_new:
7563  * 
7564  * Creates a new #GtkWindowGroup object. Grabs added with
7565  * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
7566  * 
7567  * Return value: a new #GtkWindowGroup. 
7568  **/
7569 GtkWindowGroup *
7570 gtk_window_group_new (void)
7571 {
7572   return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
7573 }
7574
7575 static void
7576 window_group_cleanup_grabs (GtkWindowGroup *group,
7577                             GtkWindow      *window)
7578 {
7579   GSList *tmp_list;
7580   GSList *to_remove = NULL;
7581
7582   tmp_list = group->grabs;
7583   while (tmp_list)
7584     {
7585       if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
7586         to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
7587       tmp_list = tmp_list->next;
7588     }
7589
7590   while (to_remove)
7591     {
7592       gtk_grab_remove (to_remove->data);
7593       g_object_unref (to_remove->data);
7594       to_remove = g_slist_delete_link (to_remove, to_remove);
7595     }
7596 }
7597
7598 /**
7599  * gtk_window_group_add_window:
7600  * @window_group: a #GtkWindowGroup
7601  * @window: the #GtkWindow to add
7602  * 
7603  * Adds a window to a #GtkWindowGroup. 
7604  **/
7605 void
7606 gtk_window_group_add_window (GtkWindowGroup *window_group,
7607                              GtkWindow      *window)
7608 {
7609   g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
7610   g_return_if_fail (GTK_IS_WINDOW (window));
7611
7612   if (window->group != window_group)
7613     {
7614       g_object_ref (window);
7615       g_object_ref (window_group);
7616       
7617       if (window->group)
7618         gtk_window_group_remove_window (window->group, window);
7619       else
7620         window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
7621
7622       window->group = window_group;
7623
7624       g_object_unref (window);
7625     }
7626 }
7627
7628 /**
7629  * gtk_window_group_remove_window:
7630  * @window_group: a #GtkWindowGroup
7631  * @window: the #GtkWindow to remove
7632  * 
7633  * Removes a window from a #GtkWindowGroup.
7634  **/
7635 void
7636 gtk_window_group_remove_window (GtkWindowGroup *window_group,
7637                                 GtkWindow      *window)
7638 {
7639   g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
7640   g_return_if_fail (GTK_IS_WINDOW (window));
7641   g_return_if_fail (window->group == window_group);
7642
7643   g_object_ref (window);
7644
7645   window_group_cleanup_grabs (window_group, window);
7646   window->group = NULL;
7647   
7648   g_object_unref (window_group);
7649   g_object_unref (window);
7650 }
7651
7652 /**
7653  * gtk_window_group_list_windows:
7654  * @window_group: a #GtkWindowGroup
7655  *
7656  * Returns a list of the #GtkWindows that belong to @window_group.
7657  *
7658  * Returns: A newly-allocated list of windows inside the group.
7659  *
7660  * Since: 2.14
7661  **/
7662 GList *
7663 gtk_window_group_list_windows (GtkWindowGroup *window_group)
7664 {
7665   GList *toplevels, *toplevel, *group_windows;
7666
7667   g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
7668
7669   group_windows = NULL;
7670   toplevels = gtk_window_list_toplevels ();
7671
7672   for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
7673     {
7674       GtkWindow *window = toplevel->data;
7675
7676       if (window_group == window->group)
7677         group_windows = g_list_prepend (group_windows, window);
7678     }
7679
7680   return g_list_reverse (group_windows);
7681 }
7682
7683 /**
7684  * gtk_window_get_group:
7685  * @window: a #GtkWindow, or %NULL
7686  *
7687  * Returns the group for @window or the default group, if
7688  * @window is %NULL or if @window does not have an explicit
7689  * window group. 
7690  *
7691  * Returns: the #GtkWindowGroup for a window or the default group
7692  *
7693  * Since: 2.10
7694  */
7695 GtkWindowGroup *
7696 gtk_window_get_group (GtkWindow *window)
7697 {
7698   if (window && window->group)
7699     return window->group;
7700   else
7701     {
7702       static GtkWindowGroup *default_group = NULL;
7703
7704       if (!default_group)
7705         default_group = gtk_window_group_new ();
7706
7707       return default_group;
7708     }
7709 }
7710
7711 /* Return the current grab widget of the given group 
7712  */
7713 GtkWidget *
7714 _gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
7715 {
7716   if (window_group->grabs)
7717     return GTK_WIDGET (window_group->grabs->data);
7718   return NULL;
7719 }
7720
7721 /*
7722   Derived from XParseGeometry() in XFree86  
7723
7724   Copyright 1985, 1986, 1987,1998  The Open Group
7725
7726   All Rights Reserved.
7727
7728   The above copyright notice and this permission notice shall be included
7729   in all copies or substantial portions of the Software.
7730
7731   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
7732   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
7733   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
7734   IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
7735   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
7736   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
7737   OTHER DEALINGS IN THE SOFTWARE.
7738
7739   Except as contained in this notice, the name of The Open Group shall
7740   not be used in advertising or otherwise to promote the sale, use or
7741   other dealings in this Software without prior written authorization
7742   from The Open Group.
7743 */
7744
7745
7746 /*
7747  *    XParseGeometry parses strings of the form
7748  *   "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
7749  *   width, height, xoffset, and yoffset are unsigned integers.
7750  *   Example:  "=80x24+300-49"
7751  *   The equal sign is optional.
7752  *   It returns a bitmask that indicates which of the four values
7753  *   were actually found in the string.  For each value found,
7754  *   the corresponding argument is updated;  for each value
7755  *   not found, the corresponding argument is left unchanged. 
7756  */
7757
7758 /* The following code is from Xlib, and is minimally modified, so we
7759  * can track any upstream changes if required.  Don't change this
7760  * code. Or if you do, put in a huge comment marking which thing
7761  * changed.
7762  */
7763
7764 static int
7765 read_int (gchar   *string,
7766           gchar  **next)
7767 {
7768   int result = 0;
7769   int sign = 1;
7770   
7771   if (*string == '+')
7772     string++;
7773   else if (*string == '-')
7774     {
7775       string++;
7776       sign = -1;
7777     }
7778
7779   for (; (*string >= '0') && (*string <= '9'); string++)
7780     {
7781       result = (result * 10) + (*string - '0');
7782     }
7783
7784   *next = string;
7785
7786   if (sign >= 0)
7787     return (result);
7788   else
7789     return (-result);
7790 }
7791
7792 /* 
7793  * Bitmask returned by XParseGeometry().  Each bit tells if the corresponding
7794  * value (x, y, width, height) was found in the parsed string.
7795  */
7796 #define NoValue         0x0000
7797 #define XValue          0x0001
7798 #define YValue          0x0002
7799 #define WidthValue      0x0004
7800 #define HeightValue     0x0008
7801 #define AllValues       0x000F
7802 #define XNegative       0x0010
7803 #define YNegative       0x0020
7804
7805 /* Try not to reformat/modify, so we can compare/sync with X sources */
7806 static int
7807 gtk_XParseGeometry (const char   *string,
7808                     int          *x,
7809                     int          *y,
7810                     unsigned int *width,   
7811                     unsigned int *height)  
7812 {
7813   int mask = NoValue;
7814   char *strind;
7815   unsigned int tempWidth, tempHeight;
7816   int tempX, tempY;
7817   char *nextCharacter;
7818
7819   /* These initializations are just to silence gcc */
7820   tempWidth = 0;
7821   tempHeight = 0;
7822   tempX = 0;
7823   tempY = 0;
7824   
7825   if ( (string == NULL) || (*string == '\0')) return(mask);
7826   if (*string == '=')
7827     string++;  /* ignore possible '=' at beg of geometry spec */
7828
7829   strind = (char *)string;
7830   if (*strind != '+' && *strind != '-' && *strind != 'x') {
7831     tempWidth = read_int(strind, &nextCharacter);
7832     if (strind == nextCharacter) 
7833       return (0);
7834     strind = nextCharacter;
7835     mask |= WidthValue;
7836   }
7837
7838   if (*strind == 'x' || *strind == 'X') {       
7839     strind++;
7840     tempHeight = read_int(strind, &nextCharacter);
7841     if (strind == nextCharacter)
7842       return (0);
7843     strind = nextCharacter;
7844     mask |= HeightValue;
7845   }
7846
7847   if ((*strind == '+') || (*strind == '-')) {
7848     if (*strind == '-') {
7849       strind++;
7850       tempX = -read_int(strind, &nextCharacter);
7851       if (strind == nextCharacter)
7852         return (0);
7853       strind = nextCharacter;
7854       mask |= XNegative;
7855
7856     }
7857     else
7858       { strind++;
7859       tempX = read_int(strind, &nextCharacter);
7860       if (strind == nextCharacter)
7861         return(0);
7862       strind = nextCharacter;
7863       }
7864     mask |= XValue;
7865     if ((*strind == '+') || (*strind == '-')) {
7866       if (*strind == '-') {
7867         strind++;
7868         tempY = -read_int(strind, &nextCharacter);
7869         if (strind == nextCharacter)
7870           return(0);
7871         strind = nextCharacter;
7872         mask |= YNegative;
7873
7874       }
7875       else
7876         {
7877           strind++;
7878           tempY = read_int(strind, &nextCharacter);
7879           if (strind == nextCharacter)
7880             return(0);
7881           strind = nextCharacter;
7882         }
7883       mask |= YValue;
7884     }
7885   }
7886         
7887   /* If strind isn't at the end of the string the it's an invalid
7888                 geometry specification. */
7889
7890   if (*strind != '\0') return (0);
7891
7892   if (mask & XValue)
7893     *x = tempX;
7894   if (mask & YValue)
7895     *y = tempY;
7896   if (mask & WidthValue)
7897     *width = tempWidth;
7898   if (mask & HeightValue)
7899     *height = tempHeight;
7900   return (mask);
7901 }
7902
7903 /**
7904  * gtk_window_parse_geometry:
7905  * @window: a #GtkWindow
7906  * @geometry: geometry string
7907  * 
7908  * Parses a standard X Window System geometry string - see the
7909  * manual page for X (type 'man X') for details on this.
7910  * gtk_window_parse_geometry() does work on all GTK+ ports
7911  * including Win32 but is primarily intended for an X environment.
7912  *
7913  * If either a size or a position can be extracted from the
7914  * geometry string, gtk_window_parse_geometry() returns %TRUE
7915  * and calls gtk_window_set_default_size() and/or gtk_window_move()
7916  * to resize/move the window.
7917  *
7918  * If gtk_window_parse_geometry() returns %TRUE, it will also
7919  * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
7920  * indicating to the window manager that the size/position of
7921  * the window was user-specified. This causes most window
7922  * managers to honor the geometry.
7923  *
7924  * Note that for gtk_window_parse_geometry() to work as expected, it has
7925  * to be called when the window has its "final" size, i.e. after calling
7926  * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
7927  * on the window.
7928  * |[
7929  * #include <gtk/gtk.h>
7930  *    
7931  * static void
7932  * fill_with_content (GtkWidget *vbox)
7933  * {
7934  *   /&ast; fill with content... &ast;/
7935  * }
7936  *    
7937  * int
7938  * main (int argc, char *argv[])
7939  * {
7940  *   GtkWidget *window, *vbox;
7941  *   GdkGeometry size_hints = {
7942  *     100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST  
7943  *   };
7944  *    
7945  *   gtk_init (&argc, &argv);
7946  *   
7947  *   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7948  *   vbox = gtk_vbox_new (FALSE, 0);
7949  *   
7950  *   gtk_container_add (GTK_CONTAINER (window), vbox);
7951  *   fill_with_content (vbox);
7952  *   gtk_widget_show_all (vbox);
7953  *   
7954  *   gtk_window_set_geometry_hints (GTK_WINDOW (window),
7955  *                                  window,
7956  *                                  &size_hints,
7957  *                                  GDK_HINT_MIN_SIZE | 
7958  *                                  GDK_HINT_BASE_SIZE | 
7959  *                                  GDK_HINT_RESIZE_INC);
7960  *   
7961  *   if (argc &gt; 1)
7962  *     {
7963  *       if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
7964  *         fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
7965  *     }
7966  *    
7967  *   gtk_widget_show_all (window);
7968  *   gtk_main ();
7969  *    
7970  *   return 0;
7971  * }
7972  * ]|
7973  *
7974  * Return value: %TRUE if string was parsed successfully
7975  **/
7976 gboolean
7977 gtk_window_parse_geometry (GtkWindow   *window,
7978                            const gchar *geometry)
7979 {
7980   gint result, x = 0, y = 0;
7981   guint w, h;
7982   GdkGravity grav;
7983   gboolean size_set, pos_set;
7984   GdkScreen *screen;
7985   
7986   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7987   g_return_val_if_fail (geometry != NULL, FALSE);
7988
7989   screen = gtk_window_check_screen (window);
7990   
7991   result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
7992
7993   size_set = FALSE;
7994   if ((result & WidthValue) || (result & HeightValue))
7995     {
7996       gtk_window_set_default_size_internal (window, 
7997                                             TRUE, result & WidthValue ? w : -1,
7998                                             TRUE, result & HeightValue ? h : -1, 
7999                                             TRUE);
8000       size_set = TRUE;
8001     }
8002
8003   gtk_window_get_size (window, (gint *)&w, (gint *)&h);
8004   
8005   grav = GDK_GRAVITY_NORTH_WEST;
8006
8007   if ((result & XNegative) && (result & YNegative))
8008     grav = GDK_GRAVITY_SOUTH_EAST;
8009   else if (result & XNegative)
8010     grav = GDK_GRAVITY_NORTH_EAST;
8011   else if (result & YNegative)
8012     grav = GDK_GRAVITY_SOUTH_WEST;
8013
8014   if ((result & XValue) == 0)
8015     x = 0;
8016
8017   if ((result & YValue) == 0)
8018     y = 0;
8019
8020   if (grav == GDK_GRAVITY_SOUTH_WEST ||
8021       grav == GDK_GRAVITY_SOUTH_EAST)
8022     y = gdk_screen_get_height (screen) - h + y;
8023
8024   if (grav == GDK_GRAVITY_SOUTH_EAST ||
8025       grav == GDK_GRAVITY_NORTH_EAST)
8026     x = gdk_screen_get_width (screen) - w + x;
8027
8028   /* we don't let you put a window offscreen; maybe some people would
8029    * prefer to be able to, but it's kind of a bogus thing to do.
8030    */
8031   if (y < 0)
8032     y = 0;
8033
8034   if (x < 0)
8035     x = 0;
8036
8037   pos_set = FALSE;
8038   if ((result & XValue) || (result & YValue))
8039     {
8040       gtk_window_set_gravity (window, grav);
8041       gtk_window_move (window, x, y);
8042       pos_set = TRUE;
8043     }
8044
8045   if (size_set || pos_set)
8046     {
8047       /* Set USSize, USPosition hints */
8048       GtkWindowGeometryInfo *info;
8049
8050       info = gtk_window_get_geometry_info (window, TRUE);
8051
8052       if (pos_set)
8053         info->mask |= GDK_HINT_USER_POS;
8054       if (size_set)
8055         info->mask |= GDK_HINT_USER_SIZE;
8056     }
8057   
8058   return result != 0;
8059 }
8060
8061 static void
8062 gtk_window_mnemonic_hash_foreach (guint      keyval,
8063                                   GSList    *targets,
8064                                   gpointer   data)
8065 {
8066   struct {
8067     GtkWindow *window;
8068     GtkWindowKeysForeachFunc func;
8069     gpointer func_data;
8070   } *info = data;
8071
8072   (*info->func) (info->window, keyval, info->window->mnemonic_modifier, TRUE, info->func_data);
8073 }
8074
8075 void
8076 _gtk_window_keys_foreach (GtkWindow                *window,
8077                           GtkWindowKeysForeachFunc func,
8078                           gpointer                 func_data)
8079 {
8080   GSList *groups;
8081   GtkMnemonicHash *mnemonic_hash;
8082
8083   struct {
8084     GtkWindow *window;
8085     GtkWindowKeysForeachFunc func;
8086     gpointer func_data;
8087   } info;
8088
8089   info.window = window;
8090   info.func = func;
8091   info.func_data = func_data;
8092
8093   mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
8094   if (mnemonic_hash)
8095     _gtk_mnemonic_hash_foreach (mnemonic_hash,
8096                                 gtk_window_mnemonic_hash_foreach, &info);
8097
8098   groups = gtk_accel_groups_from_object (G_OBJECT (window));
8099   while (groups)
8100     {
8101       GtkAccelGroup *group = groups->data;
8102       gint i;
8103
8104       for (i = 0; i < group->n_accels; i++)
8105         {
8106           GtkAccelKey *key = &group->priv_accels[i].key;
8107           
8108           if (key->accel_key)
8109             (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
8110         }
8111       
8112       groups = groups->next;
8113     }
8114 }
8115
8116 static void
8117 gtk_window_keys_changed (GtkWindow *window)
8118 {
8119   gtk_window_free_key_hash (window);
8120   gtk_window_get_key_hash (window);
8121 }
8122
8123 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
8124
8125 struct _GtkWindowKeyEntry
8126 {
8127   guint keyval;
8128   guint modifiers;
8129   guint is_mnemonic : 1;
8130 };
8131
8132 static void 
8133 window_key_entry_destroy (gpointer data)
8134 {
8135   g_slice_free (GtkWindowKeyEntry, data);
8136 }
8137
8138 static void
8139 add_to_key_hash (GtkWindow      *window,
8140                  guint           keyval,
8141                  GdkModifierType modifiers,
8142                  gboolean        is_mnemonic,
8143                  gpointer        data)
8144 {
8145   GtkKeyHash *key_hash = data;
8146
8147   GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
8148
8149   entry->keyval = keyval;
8150   entry->modifiers = modifiers;
8151   entry->is_mnemonic = is_mnemonic;
8152
8153   /* GtkAccelGroup stores lowercased accelerators. To deal
8154    * with this, if <Shift> was specified, uppercase.
8155    */
8156   if (modifiers & GDK_SHIFT_MASK)
8157     {
8158       if (keyval == GDK_Tab)
8159         keyval = GDK_ISO_Left_Tab;
8160       else
8161         keyval = gdk_keyval_to_upper (keyval);
8162     }
8163   
8164   _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
8165 }
8166
8167 static GtkKeyHash *
8168 gtk_window_get_key_hash (GtkWindow *window)
8169 {
8170   GdkScreen *screen = gtk_window_check_screen (window);
8171   GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
8172   
8173   if (key_hash)
8174     return key_hash;
8175   
8176   key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
8177                                 (GDestroyNotify)window_key_entry_destroy);
8178   _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
8179   g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
8180
8181   return key_hash;
8182 }
8183
8184 static void
8185 gtk_window_free_key_hash (GtkWindow *window)
8186 {
8187   GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
8188   if (key_hash)
8189     {
8190       _gtk_key_hash_free (key_hash);
8191       g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
8192     }
8193 }
8194
8195 /**
8196  * gtk_window_activate_key:
8197  * @window:  a #GtkWindow
8198  * @event:   a #GdkEventKey
8199  *
8200  * Activates mnemonics and accelerators for this #GtkWindow. This is normally
8201  * called by the default ::key_press_event handler for toplevel windows,
8202  * however in some cases it may be useful to call this directly when
8203  * overriding the standard key handling for a toplevel window.
8204  *
8205  * Return value: %TRUE if a mnemonic or accelerator was found and activated.
8206  **/
8207 gboolean
8208 gtk_window_activate_key (GtkWindow   *window,
8209                          GdkEventKey *event)
8210 {
8211   GtkKeyHash *key_hash;
8212   GtkWindowKeyEntry *found_entry = NULL;
8213   gboolean enable_mnemonics;
8214   gboolean enable_accels;
8215
8216   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8217   g_return_val_if_fail (event != NULL, FALSE);
8218
8219   key_hash = gtk_window_get_key_hash (window);
8220
8221   if (key_hash)
8222     {
8223       GSList *tmp_list;
8224       GSList *entries = _gtk_key_hash_lookup (key_hash,
8225                                               event->hardware_keycode,
8226                                               event->state,
8227                                               gtk_accelerator_get_default_mod_mask (),
8228                                               event->group);
8229
8230       g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
8231                     "gtk-enable-mnemonics", &enable_mnemonics,
8232                     "gtk-enable-accels", &enable_accels,
8233                     NULL);
8234
8235       for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
8236         {
8237           GtkWindowKeyEntry *entry = tmp_list->data;
8238           if (entry->is_mnemonic)
8239             {
8240               if (enable_mnemonics)
8241                 {
8242                   found_entry = entry;
8243                   break;
8244                 }
8245             }
8246           else 
8247             {
8248               if (enable_accels && !found_entry)
8249                 {
8250                   found_entry = entry;
8251                 }
8252             }
8253         }
8254
8255       g_slist_free (entries);
8256     }
8257
8258   if (found_entry)
8259     {
8260       if (found_entry->is_mnemonic)
8261         {
8262           if (enable_mnemonics)
8263             return gtk_window_mnemonic_activate (window, found_entry->keyval,
8264                                                  found_entry->modifiers);
8265         }
8266       else
8267         {
8268           if (enable_accels)
8269             return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
8270                                               found_entry->modifiers);
8271         }
8272     }
8273
8274   return FALSE;
8275 }
8276
8277 static void
8278 window_update_has_focus (GtkWindow *window)
8279 {
8280   GtkWidget *widget = GTK_WIDGET (window);
8281   gboolean has_focus = window->has_toplevel_focus && window->is_active;
8282   
8283   if (has_focus != window->has_focus)
8284     {
8285       window->has_focus = has_focus;
8286       
8287       if (has_focus)
8288         {
8289           if (window->focus_widget &&
8290               window->focus_widget != widget &&
8291               !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
8292             do_focus_change (window->focus_widget, TRUE);       
8293         }
8294       else
8295         {
8296           if (window->focus_widget &&
8297               window->focus_widget != widget &&
8298               GTK_WIDGET_HAS_FOCUS (window->focus_widget))
8299             do_focus_change (window->focus_widget, FALSE);
8300         }
8301     }
8302 }
8303
8304 /**
8305  * _gtk_window_set_is_active:
8306  * @window: a #GtkWindow
8307  * @is_active: %TRUE if the window is in the currently active toplevel
8308  * 
8309  * Internal function that sets whether the #GtkWindow is part
8310  * of the currently active toplevel window (taking into account inter-process
8311  * embedding.)
8312  **/
8313 void
8314 _gtk_window_set_is_active (GtkWindow *window,
8315                            gboolean   is_active)
8316 {
8317   g_return_if_fail (GTK_IS_WINDOW (window));
8318
8319   is_active = is_active != FALSE;
8320
8321   if (is_active != window->is_active)
8322     {
8323       window->is_active = is_active;
8324       window_update_has_focus (window);
8325
8326       g_object_notify (G_OBJECT (window), "is-active");
8327     }
8328 }
8329
8330 /**
8331  * _gtk_window_set_is_toplevel:
8332  * @window: a #GtkWindow
8333  * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
8334  * parent of the root window); %FALSE if it is not (for example, for an
8335  * in-process, parented GtkPlug)
8336  *
8337  * Internal function used by #GtkPlug when it gets parented/unparented by a
8338  * #GtkSocket.  This keeps the @window's #GTK_TOPLEVEL flag in sync with the
8339  * global list of toplevel windows.
8340  */
8341 void
8342 _gtk_window_set_is_toplevel (GtkWindow *window,
8343                              gboolean   is_toplevel)
8344 {
8345   if (GTK_WIDGET_TOPLEVEL (window))
8346     g_assert (g_slist_find (toplevel_list, window) != NULL);
8347   else
8348     g_assert (g_slist_find (toplevel_list, window) == NULL);
8349
8350   if (is_toplevel == GTK_WIDGET_TOPLEVEL (window))
8351     return;
8352
8353   if (is_toplevel)
8354     {
8355       GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
8356       toplevel_list = g_slist_prepend (toplevel_list, window);
8357     }
8358   else
8359     {
8360       GTK_WIDGET_UNSET_FLAGS (window, GTK_TOPLEVEL);
8361       toplevel_list = g_slist_remove (toplevel_list, window);
8362     }
8363 }
8364
8365 /**
8366  * _gtk_window_set_has_toplevel_focus:
8367  * @window: a #GtkWindow
8368  * @has_toplevel_focus: %TRUE if the in
8369  * 
8370  * Internal function that sets whether the keyboard focus for the
8371  * toplevel window (taking into account inter-process embedding.)
8372  **/
8373 void
8374 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
8375                                    gboolean   has_toplevel_focus)
8376 {
8377   g_return_if_fail (GTK_IS_WINDOW (window));
8378   
8379   has_toplevel_focus = has_toplevel_focus != FALSE;
8380
8381   if (has_toplevel_focus != window->has_toplevel_focus)
8382     {
8383       window->has_toplevel_focus = has_toplevel_focus;
8384       window_update_has_focus (window);
8385
8386       g_object_notify (G_OBJECT (window), "has-toplevel-focus");
8387     }
8388 }
8389
8390 /**
8391  * gtk_window_set_auto_startup_notification:
8392  * @setting: %TRUE to automatically do startup notification
8393  *
8394  * By default, after showing the first #GtkWindow, GTK+ calls 
8395  * gdk_notify_startup_complete().  Call this function to disable 
8396  * the automatic startup notification. You might do this if your 
8397  * first window is a splash screen, and you want to delay notification 
8398  * until after your real main window has been shown, for example.
8399  *
8400  * In that example, you would disable startup notification
8401  * temporarily, show your splash screen, then re-enable it so that
8402  * showing the main window would automatically result in notification.
8403  * 
8404  * Since: 2.2
8405  **/
8406 void
8407 gtk_window_set_auto_startup_notification (gboolean setting)
8408 {
8409   disable_startup_notification = !setting;
8410 }
8411
8412 #if defined (G_OS_WIN32) && !defined (_WIN64)
8413
8414 #undef gtk_window_set_icon_from_file
8415
8416 gboolean
8417 gtk_window_set_icon_from_file (GtkWindow   *window,
8418                                const gchar *filename,
8419                                GError     **err)
8420 {
8421   gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, err);
8422   gboolean retval;
8423
8424   if (utf8_filename == NULL)
8425     return FALSE;
8426
8427   retval = gtk_window_set_icon_from_file_utf8 (window, utf8_filename, err);
8428
8429   g_free (utf8_filename);
8430
8431   return retval;
8432 }
8433
8434 #undef gtk_window_set_default_icon_from_file
8435
8436 gboolean
8437 gtk_window_set_default_icon_from_file (const gchar *filename,
8438                                        GError     **err)
8439 {
8440   gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, err);
8441   gboolean retval;
8442
8443   if (utf8_filename == NULL)
8444     return FALSE;
8445
8446   retval = gtk_window_set_default_icon_from_file_utf8 (utf8_filename, err);
8447
8448   g_free (utf8_filename);
8449
8450   return retval;
8451 }
8452
8453 #endif
8454
8455 #define __GTK_WINDOW_C__
8456 #include "gtkaliasdef.c"