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