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