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