]> Pileus Git - ~andy/gtk/blob - gtk/gtkwindow.c
deprecated floating/sink API and implemented it in terms of the GObject
[~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  * @window: a #GtkWindow
2471  * @setting: %TRUE to decorate the window as deletable
2472  *
2473  * By default, windows have a close button in the window frame. Some 
2474  * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to 
2475  * disable this button. If you set the deletable property to %FALSE
2476  * using this function, GTK+ will do its best to convince the window
2477  * manager not to show a close button. Depending on the system, this
2478  * function may not have any effect when called on a window that is
2479  * already visible, so you should call it before calling gtk_window_show().
2480  *
2481  * On Windows, this function always works, since there's no window manager
2482  * policy involved.
2483  *
2484  * Since: 2.10
2485  */
2486 void
2487 gtk_window_set_deletable (GtkWindow *window,
2488                           gboolean   setting)
2489 {
2490   GtkWindowPrivate *priv;
2491
2492   g_return_if_fail (GTK_IS_WINDOW (window));
2493
2494   priv = GTK_WINDOW_GET_PRIVATE (window);
2495
2496   setting = setting != FALSE;
2497
2498   if (setting == priv->deletable)
2499     return;
2500
2501   priv->deletable = setting;
2502   
2503   if (GTK_WIDGET (window)->window)
2504     {
2505       if (priv->deletable)
2506         gdk_window_set_functions (GTK_WIDGET (window)->window,
2507                                   GDK_FUNC_ALL);
2508       else
2509         gdk_window_set_functions (GTK_WIDGET (window)->window,
2510                                   GDK_FUNC_ALL | GDK_FUNC_CLOSE);
2511     }
2512
2513   g_object_notify (G_OBJECT (window), "deletable");  
2514 }
2515
2516 /**
2517  * gtk_window_get_deletable:
2518  * @window: a #GtkWindow
2519  *
2520  * Returns whether the window has been set to have a close button
2521  * via gtk_window_set_deletable().
2522  *
2523  * Return value: %TRUE if the window has been set to have a close button
2524  **/
2525 gboolean
2526 gtk_window_get_deletable (GtkWindow *window)
2527 {
2528   GtkWindowPrivate *priv;
2529
2530   g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
2531
2532   priv = GTK_WINDOW_GET_PRIVATE (window);
2533
2534   return priv->deletable;
2535 }
2536
2537 static GtkWindowIconInfo*
2538 get_icon_info (GtkWindow *window)
2539 {
2540   return g_object_get_data (G_OBJECT (window),
2541                             "gtk-window-icon-info");
2542 }
2543      
2544 static void
2545 free_icon_info (GtkWindowIconInfo *info)
2546 {
2547   g_free (info->icon_name);
2548   g_free (info);
2549 }
2550
2551
2552 static GtkWindowIconInfo*
2553 ensure_icon_info (GtkWindow *window)
2554 {
2555   GtkWindowIconInfo *info;
2556
2557   info = get_icon_info (window);
2558   
2559   if (info == NULL)
2560     {
2561       info = g_new0 (GtkWindowIconInfo, 1);
2562       g_object_set_data_full (G_OBJECT (window),
2563                               I_("gtk-window-icon-info"),
2564                               info,
2565                               (GDestroyNotify)free_icon_info);
2566     }
2567
2568   return info;
2569 }
2570
2571 typedef struct {
2572   guint serial;
2573   GdkPixmap *pixmap;
2574   GdkPixmap *mask;
2575 } ScreenIconInfo;
2576
2577 static ScreenIconInfo *
2578 get_screen_icon_info (GdkScreen *screen)
2579 {
2580   ScreenIconInfo *info = g_object_get_data (G_OBJECT (screen), 
2581                                             "gtk-window-default-icon-pixmap");
2582   if (!info)
2583     {
2584       info = g_new0 (ScreenIconInfo, 1);
2585       g_object_set_data (G_OBJECT (screen), I_("gtk-window-default-icon-pixmap"), info);
2586     }
2587
2588   if (info->serial != default_icon_serial)
2589     {
2590       if (info->pixmap)
2591         {
2592           g_object_remove_weak_pointer (G_OBJECT (info->pixmap), (gpointer*)&info->pixmap);
2593           info->pixmap = NULL;
2594         }
2595           
2596       if (info->mask)
2597         {
2598           g_object_remove_weak_pointer (G_OBJECT (info->mask), (gpointer*)&info->mask);
2599           info->mask = NULL;
2600         }
2601
2602       info->serial = default_icon_serial;
2603     }
2604   
2605   return info;
2606 }
2607
2608 static void
2609 get_pixmap_and_mask (GdkWindow          *window,
2610                      GtkWindowIconInfo  *parent_info,
2611                      gboolean            is_default_list,
2612                      GList              *icon_list,
2613                      GdkPixmap         **pmap_return,
2614                      GdkBitmap         **mask_return)
2615 {
2616   GdkScreen *screen = gdk_drawable_get_screen (window);
2617   ScreenIconInfo *default_icon_info = get_screen_icon_info (screen);
2618   GdkPixbuf *best_icon;
2619   GList *tmp_list;
2620   int best_size;
2621   
2622   *pmap_return = NULL;
2623   *mask_return = NULL;
2624   
2625   if (is_default_list &&
2626       default_icon_info->pixmap != NULL)
2627     {
2628       /* Use shared icon pixmap for all windows on this screen.
2629        */
2630       if (default_icon_info->pixmap)
2631         g_object_ref (default_icon_info->pixmap);
2632       if (default_icon_info->mask)
2633         g_object_ref (default_icon_info->mask);
2634
2635       *pmap_return = default_icon_info->pixmap;
2636       *mask_return = default_icon_info->mask;
2637     }
2638   else if (parent_info && parent_info->icon_pixmap)
2639     {
2640       if (parent_info->icon_pixmap)
2641         g_object_ref (parent_info->icon_pixmap);
2642       if (parent_info->icon_mask)
2643         g_object_ref (parent_info->icon_mask);
2644       
2645       *pmap_return = parent_info->icon_pixmap;
2646       *mask_return = parent_info->icon_mask;
2647     }
2648   else
2649     {
2650 #define IDEAL_SIZE 48
2651   
2652       best_size = G_MAXINT;
2653       best_icon = NULL;
2654       tmp_list = icon_list;
2655       while (tmp_list != NULL)
2656         {
2657           GdkPixbuf *pixbuf = tmp_list->data;
2658           int this;
2659       
2660           /* average width and height - if someone passes in a rectangular
2661            * icon they deserve what they get.
2662            */
2663           this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
2664           this /= 2;
2665       
2666           if (best_icon == NULL)
2667             {
2668               best_icon = pixbuf;
2669               best_size = this;
2670             }
2671           else
2672             {
2673               /* icon is better if it's 32 pixels or larger, and closer to
2674                * the ideal size than the current best.
2675                */
2676               if (this >= 32 &&
2677                   (ABS (best_size - IDEAL_SIZE) <
2678                    ABS (this - IDEAL_SIZE)))
2679                 {
2680                   best_icon = pixbuf;
2681                   best_size = this;
2682                 }
2683             }
2684
2685           tmp_list = tmp_list->next;
2686         }
2687
2688       if (best_icon)
2689         gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
2690                                                         gdk_screen_get_system_colormap (screen),
2691                                                         pmap_return,
2692                                                         mask_return,
2693                                                         128);
2694
2695       /* Save pmap/mask for others to use if appropriate */
2696       if (parent_info)
2697         {
2698           parent_info->icon_pixmap = *pmap_return;
2699           parent_info->icon_mask = *mask_return;
2700
2701           if (parent_info->icon_pixmap)
2702             g_object_ref (parent_info->icon_pixmap);
2703           if (parent_info->icon_mask)
2704             g_object_ref (parent_info->icon_mask);
2705         }
2706       else if (is_default_list)
2707         {
2708           default_icon_info->pixmap = *pmap_return;
2709           default_icon_info->mask = *mask_return;
2710
2711           if (default_icon_info->pixmap)
2712             g_object_add_weak_pointer (G_OBJECT (default_icon_info->pixmap),
2713                                        (gpointer*)&default_icon_info->pixmap);
2714           if (default_icon_info->mask) 
2715             g_object_add_weak_pointer (G_OBJECT (default_icon_info->mask),
2716                                        (gpointer*)&default_icon_info->mask);
2717         }
2718     }
2719 }
2720
2721 static GList *
2722 icon_list_from_theme (GtkWidget    *widget,
2723                       const gchar  *name)
2724 {
2725   GList *list;
2726
2727   GtkIconTheme *icon_theme;
2728   GdkPixbuf *icon;
2729   gint *sizes;
2730   gint i;
2731
2732   icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
2733
2734   sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
2735
2736   list = NULL;
2737   for (i = 0; sizes[i]; i++)
2738     {      
2739       /* FIXME
2740        * We need an EWMH extension to handle scalable icons 
2741        * by passing their name to the WM. For now just use a 
2742        * fixed size of 48.
2743        */ 
2744       if (sizes[i] == -1)
2745         icon = gtk_icon_theme_load_icon (icon_theme, name,
2746                                          48, 0, NULL);
2747       else
2748         icon = gtk_icon_theme_load_icon (icon_theme, name,
2749                                          sizes[i], 0, NULL);
2750       if (icon)
2751         list = g_list_append (list, icon);
2752     }
2753
2754   g_free (sizes);
2755
2756   return list;
2757 }
2758
2759
2760 static void
2761 gtk_window_realize_icon (GtkWindow *window)
2762 {
2763   GtkWidget *widget;
2764   GtkWindowIconInfo *info;
2765   GList *icon_list;
2766
2767   widget = GTK_WIDGET (window);
2768
2769   g_return_if_fail (widget->window != NULL);
2770
2771   /* no point setting an icon on override-redirect */
2772   if (window->type == GTK_WINDOW_POPUP)
2773     return;
2774
2775   icon_list = NULL;
2776   
2777   info = ensure_icon_info (window);
2778
2779   if (info->realized)
2780     return;
2781
2782   g_return_if_fail (info->icon_pixmap == NULL);
2783   g_return_if_fail (info->icon_mask == NULL);
2784   
2785   info->using_default_icon = FALSE;
2786   info->using_parent_icon = FALSE;
2787   info->using_themed_icon = FALSE;
2788   
2789   icon_list = info->icon_list;
2790
2791   /* Look up themed icon */
2792   if (icon_list == NULL && info->icon_name) 
2793     {
2794       icon_list = icon_list_from_theme (widget, info->icon_name);
2795       if (icon_list)
2796         info->using_themed_icon = TRUE;
2797     }
2798
2799   /* Inherit from transient parent */
2800   if (icon_list == NULL && window->transient_parent)
2801     {
2802       icon_list = ensure_icon_info (window->transient_parent)->icon_list;
2803       if (icon_list)
2804         info->using_parent_icon = TRUE;
2805     }      
2806
2807   /* Inherit from default */
2808   if (icon_list == NULL)
2809     {
2810       icon_list = default_icon_list;
2811       if (icon_list)
2812         info->using_default_icon = TRUE;
2813     }
2814
2815   /* Look up themed icon */
2816   if (icon_list == NULL && default_icon_name) 
2817     {
2818       icon_list = icon_list_from_theme (widget, default_icon_name);
2819       info->using_default_icon = TRUE;
2820       info->using_themed_icon = TRUE;  
2821     }
2822   
2823   gdk_window_set_icon_list (widget->window, icon_list);
2824
2825   get_pixmap_and_mask (widget->window,
2826                        info->using_parent_icon ? ensure_icon_info (window->transient_parent) : NULL,
2827                        info->using_default_icon,
2828                        icon_list,
2829                        &info->icon_pixmap,
2830                        &info->icon_mask);
2831   
2832   /* This is a slight ICCCM violation since it's a color pixmap not
2833    * a bitmap, but everyone does it.
2834    */
2835   gdk_window_set_icon (widget->window,
2836                        NULL,
2837                        info->icon_pixmap,
2838                        info->icon_mask);
2839
2840   info->realized = TRUE;
2841   
2842   if (info->using_themed_icon) 
2843     {
2844       GtkIconTheme *icon_theme;
2845
2846       g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
2847       g_list_free (icon_list);
2848  
2849       icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
2850       g_signal_connect (icon_theme, "changed",
2851                         G_CALLBACK (update_themed_icon), window);
2852     }
2853 }
2854
2855 static void
2856 gtk_window_unrealize_icon (GtkWindow *window)
2857 {
2858   GtkWindowIconInfo *info;
2859
2860   info = get_icon_info (window);
2861
2862   if (info == NULL)
2863     return;
2864   
2865   if (info->icon_pixmap)
2866     g_object_unref (info->icon_pixmap);
2867
2868   if (info->icon_mask)
2869     g_object_unref (info->icon_mask);
2870
2871   info->icon_pixmap = NULL;
2872   info->icon_mask = NULL;
2873
2874   if (info->using_themed_icon)
2875     {
2876       GtkIconTheme *icon_theme;
2877
2878       icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
2879
2880       g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
2881     }
2882     
2883   /* We don't clear the properties on the window, just figure the
2884    * window is going away.
2885    */
2886
2887   info->realized = FALSE;
2888
2889 }
2890
2891 /**
2892  * gtk_window_set_icon_list:
2893  * @window: a #GtkWindow
2894  * @list: list of #GdkPixbuf
2895  *
2896  * Sets up the icon representing a #GtkWindow. The icon is used when
2897  * the window is minimized (also known as iconified).  Some window
2898  * managers or desktop environments may also place it in the window
2899  * frame, or display it in other contexts.
2900  *
2901  * gtk_window_set_icon_list() allows you to pass in the same icon in
2902  * several hand-drawn sizes. The list should contain the natural sizes
2903  * your icon is available in; that is, don't scale the image before
2904  * passing it to GTK+. Scaling is postponed until the last minute,
2905  * when the desired final size is known, to allow best quality.
2906  *
2907  * By passing several sizes, you may improve the final image quality
2908  * of the icon, by reducing or eliminating automatic image scaling.
2909  *
2910  * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
2911  * larger images (64x64, 128x128) if you have them.
2912  *
2913  * See also gtk_window_set_default_icon_list() to set the icon
2914  * for all windows in your application in one go.
2915  *
2916  * Note that transient windows (those who have been set transient for another
2917  * window using gtk_window_set_transient_for()) will inherit their
2918  * icon from their transient parent. So there's no need to explicitly
2919  * set the icon on transient windows.
2920  **/
2921 void
2922 gtk_window_set_icon_list (GtkWindow  *window,
2923                           GList      *list)
2924 {
2925   GtkWindowIconInfo *info;
2926
2927   g_return_if_fail (GTK_IS_WINDOW (window));
2928
2929   info = ensure_icon_info (window);
2930
2931   if (info->icon_list == list) /* check for NULL mostly */
2932     return;
2933
2934   g_list_foreach (list,
2935                   (GFunc) g_object_ref, NULL);
2936
2937   g_list_foreach (info->icon_list,
2938                   (GFunc) g_object_unref, NULL);
2939
2940   g_list_free (info->icon_list);
2941
2942   info->icon_list = g_list_copy (list);
2943
2944   g_object_notify (G_OBJECT (window), "icon");
2945   
2946   gtk_window_unrealize_icon (window);
2947   
2948   if (GTK_WIDGET_REALIZED (window))
2949     gtk_window_realize_icon (window);
2950
2951   /* We could try to update our transient children, but I don't think
2952    * it's really worth it. If we did it, the best way would probably
2953    * be to have children connect to notify::icon-list
2954    */
2955 }
2956
2957 /**
2958  * gtk_window_get_icon_list:
2959  * @window: a #GtkWindow
2960  * 
2961  * Retrieves the list of icons set by gtk_window_set_icon_list().
2962  * The list is copied, but the reference count on each
2963  * member won't be incremented.
2964  * 
2965  * Return value: copy of window's icon list
2966  **/
2967 GList*
2968 gtk_window_get_icon_list (GtkWindow  *window)
2969 {
2970   GtkWindowIconInfo *info;
2971   
2972   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2973
2974   info = get_icon_info (window);
2975
2976   if (info)
2977     return g_list_copy (info->icon_list);
2978   else
2979     return NULL;  
2980 }
2981
2982 /**
2983  * gtk_window_set_icon:
2984  * @window: a #GtkWindow
2985  * @icon: icon image, or %NULL
2986  * 
2987  * Sets up the icon representing a #GtkWindow. This icon is used when
2988  * the window is minimized (also known as iconified).  Some window
2989  * managers or desktop environments may also place it in the window
2990  * frame, or display it in other contexts.
2991  *
2992  * The icon should be provided in whatever size it was naturally
2993  * drawn; that is, don't scale the image before passing it to
2994  * GTK+. Scaling is postponed until the last minute, when the desired
2995  * final size is known, to allow best quality.
2996  *
2997  * If you have your icon hand-drawn in multiple sizes, use
2998  * gtk_window_set_icon_list(). Then the best size will be used.
2999  *
3000  * This function is equivalent to calling gtk_window_set_icon_list()
3001  * with a 1-element list.
3002  *
3003  * See also gtk_window_set_default_icon_list() to set the icon
3004  * for all windows in your application in one go.
3005  **/
3006 void
3007 gtk_window_set_icon (GtkWindow  *window,
3008                      GdkPixbuf  *icon)
3009 {
3010   GList *list;
3011   
3012   g_return_if_fail (GTK_IS_WINDOW (window));
3013   g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3014
3015   list = NULL;
3016
3017   if (icon)
3018     list = g_list_append (list, icon);
3019   
3020   gtk_window_set_icon_list (window, list);
3021   g_list_free (list);  
3022 }
3023
3024
3025 static void 
3026 update_themed_icon (GtkIconTheme *icon_theme,
3027                     GtkWindow    *window)
3028 {
3029   g_object_notify (G_OBJECT (window), "icon");
3030   
3031   gtk_window_unrealize_icon (window);
3032   
3033   if (GTK_WIDGET_REALIZED (window))
3034     gtk_window_realize_icon (window);  
3035 }
3036
3037 /**
3038  * gtk_window_set_icon_name:
3039  * @window: a #GtkWindow
3040  * @name: the name of the themed icon
3041  *
3042  * Sets the icon for the window from a named themed icon. See
3043  * the docs for #GtkIconTheme for more details. 
3044  * 
3045  * Note that this has nothing to do with the WM_ICON_NAME 
3046  * property which is mentioned in the ICCCM.
3047  *
3048  * Since: 2.6
3049  */
3050 void 
3051 gtk_window_set_icon_name (GtkWindow   *window,
3052                           const gchar *name)
3053 {
3054   GtkWindowIconInfo *info;
3055   gchar *tmp;
3056   
3057   g_return_if_fail (GTK_IS_WINDOW (window));
3058
3059   info = ensure_icon_info (window);
3060
3061   tmp = info->icon_name;
3062   info->icon_name = g_strdup (name);
3063   g_free (tmp);
3064
3065   g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3066   g_list_free (info->icon_list);
3067   info->icon_list = NULL;
3068   
3069   update_themed_icon (NULL, window);
3070
3071   g_object_notify (G_OBJECT (window), "icon-name");
3072 }
3073
3074 /**
3075  * gtk_window_get_icon_name:
3076  * @window: a #GtkWindow
3077  *
3078  * Returns the name of the themed icon for the window,
3079  * see gtk_window_set_icon_name().
3080  *
3081  * Returns: the icon name or %NULL if the window has 
3082  * no themed icon
3083  *
3084  * Since: 2.6
3085  */
3086 G_CONST_RETURN gchar *
3087 gtk_window_get_icon_name (GtkWindow *window)
3088 {
3089   GtkWindowIconInfo *info;
3090
3091   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3092
3093   info = ensure_icon_info (window);
3094
3095   return info->icon_name;
3096 }
3097
3098 /**
3099  * gtk_window_get_icon:
3100  * @window: a #GtkWindow
3101  * 
3102  * Gets the value set by gtk_window_set_icon() (or if you've
3103  * called gtk_window_set_icon_list(), gets the first icon in
3104  * the icon list).
3105  * 
3106  * Return value: icon for window
3107  **/
3108 GdkPixbuf*
3109 gtk_window_get_icon (GtkWindow  *window)
3110 {
3111   GtkWindowIconInfo *info;
3112
3113   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3114
3115   info = get_icon_info (window);
3116   if (info && info->icon_list)
3117     return GDK_PIXBUF (info->icon_list->data);
3118   else
3119     return NULL;
3120 }
3121
3122 /* Load pixbuf, printing warning on failure if error == NULL
3123  */
3124 static GdkPixbuf *
3125 load_pixbuf_verbosely (const char *filename,
3126                        GError    **err)
3127 {
3128   GError *local_err = NULL;
3129   GdkPixbuf *pixbuf;
3130
3131   pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3132
3133   if (!pixbuf)
3134     {
3135       if (err)
3136         *err = local_err;
3137       else
3138         {
3139           g_warning ("Error loading icon from file '%s':\n\t%s",
3140                      filename, local_err->message);
3141           g_error_free (local_err);
3142         }
3143     }
3144
3145   return pixbuf;
3146 }
3147
3148 /**
3149  * gtk_window_set_icon_from_file:
3150  * @window: a #GtkWindow
3151  * @filename: location of icon file
3152  * @err: location to store error, or %NULL.
3153  *
3154  * Sets the icon for @window.  
3155  * Warns on failure if @err is %NULL.
3156  *
3157  * This function is equivalent to calling gtk_window_set_icon()
3158  * with a pixbuf created by loading the image from @filename.
3159  *
3160  * Returns: %TRUE if setting the icon succeeded.
3161  *
3162  * Since: 2.2
3163  **/
3164 gboolean
3165 gtk_window_set_icon_from_file (GtkWindow   *window,
3166                                const gchar *filename,
3167                                GError     **err)
3168 {
3169   GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3170
3171   if (pixbuf)
3172     {
3173       gtk_window_set_icon (window, pixbuf);
3174       g_object_unref (pixbuf);
3175       
3176       return TRUE;
3177     }
3178   else
3179     return FALSE;
3180 }
3181
3182 /**
3183  * gtk_window_set_default_icon_list:
3184  * @list: a list of #GdkPixbuf
3185  *
3186  * Sets an icon list to be used as fallback for windows that haven't
3187  * had gtk_window_set_icon_list() called on them to set up a
3188  * window-specific icon list. This function allows you to set up the
3189  * icon for all windows in your app at once.
3190  *
3191  * See gtk_window_set_icon_list() for more details.
3192  * 
3193  **/
3194 void
3195 gtk_window_set_default_icon_list (GList *list)
3196 {
3197   GList *toplevels;
3198   GList *tmp_list;
3199   if (list == default_icon_list)
3200     return;
3201
3202   /* Update serial so we don't used cached pixmaps/masks
3203    */
3204   default_icon_serial++;
3205   
3206   g_list_foreach (list,
3207                   (GFunc) g_object_ref, NULL);
3208
3209   g_list_foreach (default_icon_list,
3210                   (GFunc) g_object_unref, NULL);
3211
3212   g_list_free (default_icon_list);
3213
3214   default_icon_list = g_list_copy (list);
3215   
3216   /* Update all toplevels */
3217   toplevels = gtk_window_list_toplevels ();
3218   tmp_list = toplevels;
3219   while (tmp_list != NULL)
3220     {
3221       GtkWindowIconInfo *info;
3222       GtkWindow *w = tmp_list->data;
3223       
3224       info = get_icon_info (w);
3225       if (info && info->using_default_icon)
3226         {
3227           gtk_window_unrealize_icon (w);
3228           if (GTK_WIDGET_REALIZED (w))
3229             gtk_window_realize_icon (w);
3230         }
3231
3232       tmp_list = tmp_list->next;
3233     }
3234   g_list_free (toplevels);
3235 }
3236
3237 /**
3238  * gtk_window_set_default_icon:
3239  * @icon: the icon
3240  *
3241  * Sets an icon to be used as fallback for windows that haven't
3242  * had gtk_window_set_icon() called on them from a pixbuf.
3243  *
3244  * Since: 2.4
3245  **/
3246 void
3247 gtk_window_set_default_icon (GdkPixbuf *icon)
3248 {
3249   GList *list;
3250   
3251   g_return_if_fail (GDK_IS_PIXBUF (icon));
3252
3253   list = g_list_prepend (NULL, icon);
3254   gtk_window_set_default_icon_list (list);
3255   g_list_free (list);
3256 }
3257
3258 /**
3259  * gtk_window_set_default_icon_name:
3260  * @name: the name of the themed icon
3261  * 
3262  * Sets an icon to be used as fallback for windows that haven't
3263  * had gtk_window_set_icon_list() called on them from a named
3264  * themed icon, see gtk_window_set_icon_name().
3265  *
3266  * Since: 2.6
3267  **/
3268 void
3269 gtk_window_set_default_icon_name (const gchar *name)
3270 {
3271   GList *tmp_list;
3272   GList *toplevels;
3273
3274   /* Update serial so we don't used cached pixmaps/masks
3275    */
3276   default_icon_serial++;
3277
3278   g_free (default_icon_name);
3279   default_icon_name = g_strdup (name);
3280
3281   g_list_foreach (default_icon_list,
3282                   (GFunc) g_object_unref, NULL);
3283
3284   g_list_free (default_icon_list);
3285   default_icon_list = NULL;
3286   
3287   /* Update all toplevels */
3288   toplevels = gtk_window_list_toplevels ();
3289   tmp_list = toplevels;
3290   while (tmp_list != NULL)
3291     {
3292       GtkWindowIconInfo *info;
3293       GtkWindow *w = tmp_list->data;
3294       
3295       info = get_icon_info (w);
3296       if (info && info->using_default_icon && info->using_themed_icon)
3297         {
3298           gtk_window_unrealize_icon (w);
3299           if (GTK_WIDGET_REALIZED (w))
3300             gtk_window_realize_icon (w);
3301         }
3302
3303       tmp_list = tmp_list->next;
3304     }
3305   g_list_free (toplevels);
3306 }
3307
3308 /**
3309  * gtk_window_set_default_icon_from_file:
3310  * @filename: location of icon file
3311  * @err: location to store error, or %NULL.
3312  *
3313  * Sets an icon to be used as fallback for windows that haven't
3314  * had gtk_window_set_icon_list() called on them from a file
3315  * on disk. Warns on failure if @err is %NULL.
3316  *
3317  * Returns: %TRUE if setting the icon succeeded.
3318  *
3319  * Since: 2.2
3320  **/
3321 gboolean
3322 gtk_window_set_default_icon_from_file (const gchar *filename,
3323                                        GError     **err)
3324 {
3325   GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3326
3327   if (pixbuf)
3328     {
3329       gtk_window_set_default_icon (pixbuf);
3330       g_object_unref (pixbuf);
3331       
3332       return TRUE;
3333     }
3334   else
3335     return FALSE;
3336 }
3337
3338 /**
3339  * gtk_window_get_default_icon_list:
3340  * 
3341  * Gets the value set by gtk_window_set_default_icon_list().
3342  * The list is a copy and should be freed with g_list_free(),
3343  * but the pixbufs in the list have not had their reference count
3344  * incremented.
3345  * 
3346  * Return value: copy of default icon list 
3347  **/
3348 GList*
3349 gtk_window_get_default_icon_list (void)
3350 {
3351   return g_list_copy (default_icon_list);
3352 }
3353
3354 static void
3355 gtk_window_set_default_size_internal (GtkWindow    *window,
3356                                       gboolean      change_width,
3357                                       gint          width,
3358                                       gboolean      change_height,
3359                                       gint          height,
3360                                       gboolean      is_geometry)
3361 {
3362   GtkWindowGeometryInfo *info;
3363
3364   g_return_if_fail (change_width == FALSE || width >= -1);
3365   g_return_if_fail (change_height == FALSE || height >= -1);
3366
3367   info = gtk_window_get_geometry_info (window, TRUE);
3368
3369   g_object_freeze_notify (G_OBJECT (window));
3370
3371   info->default_is_geometry = is_geometry != FALSE;
3372
3373   if (change_width)
3374     {
3375       if (width == 0)
3376         width = 1;
3377
3378       if (width < 0)
3379         width = -1;
3380
3381       info->default_width = width;
3382
3383       g_object_notify (G_OBJECT (window), "default-width");
3384     }
3385
3386   if (change_height)
3387     {
3388       if (height == 0)
3389         height = 1;
3390
3391       if (height < 0)
3392         height = -1;
3393
3394       info->default_height = height;
3395       
3396       g_object_notify (G_OBJECT (window), "default-height");
3397     }
3398   
3399   g_object_thaw_notify (G_OBJECT (window));
3400   
3401   gtk_widget_queue_resize (GTK_WIDGET (window));
3402 }
3403
3404 /**
3405  * gtk_window_set_default_size:
3406  * @window: a #GtkWindow
3407  * @width: width in pixels, or -1 to unset the default width
3408  * @height: height in pixels, or -1 to unset the default height
3409  *
3410  * Sets the default size of a window. If the window's "natural" size
3411  * (its size request) is larger than the default, the default will be
3412  * ignored. More generally, if the default size does not obey the
3413  * geometry hints for the window (gtk_window_set_geometry_hints() can
3414  * be used to set these explicitly), the default size will be clamped
3415  * to the nearest permitted size.
3416  * 
3417  * Unlike gtk_widget_set_size_request(), which sets a size request for
3418  * a widget and thus would keep users from shrinking the window, this
3419  * function only sets the initial size, just as if the user had
3420  * resized the window themselves. Users can still shrink the window
3421  * again as they normally would. Setting a default size of -1 means to
3422  * use the "natural" default size (the size request of the window).
3423  *
3424  * For more control over a window's initial size and how resizing works,
3425  * investigate gtk_window_set_geometry_hints().
3426  *
3427  * For some uses, gtk_window_resize() is a more appropriate function.
3428  * gtk_window_resize() changes the current size of the window, rather
3429  * than the size to be used on initial display. gtk_window_resize() always
3430  * affects the window itself, not the geometry widget.
3431  *
3432  * The default size of a window only affects the first time a window is
3433  * shown; if a window is hidden and re-shown, it will remember the size
3434  * it had prior to hiding, rather than using the default size.
3435  *
3436  * Windows can't actually be 0x0 in size, they must be at least 1x1, but
3437  * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
3438  **/
3439 void       
3440 gtk_window_set_default_size (GtkWindow   *window,
3441                              gint         width,
3442                              gint         height)
3443 {
3444   g_return_if_fail (GTK_IS_WINDOW (window));
3445   g_return_if_fail (width >= -1);
3446   g_return_if_fail (height >= -1);
3447
3448   gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
3449 }
3450
3451 /**
3452  * gtk_window_get_default_size:
3453  * @window: a #GtkWindow
3454  * @width: location to store the default width, or %NULL
3455  * @height: location to store the default height, or %NULL
3456  *
3457  * Gets the default size of the window. A value of -1 for the width or
3458  * height indicates that a default size has not been explicitly set
3459  * for that dimension, so the "natural" size of the window will be
3460  * used.
3461  * 
3462  **/
3463 void
3464 gtk_window_get_default_size (GtkWindow *window,
3465                              gint      *width,
3466                              gint      *height)
3467 {
3468   GtkWindowGeometryInfo *info;
3469
3470   g_return_if_fail (GTK_IS_WINDOW (window));
3471
3472   info = gtk_window_get_geometry_info (window, FALSE);
3473
3474   if (width)
3475     *width = info ? info->default_width : -1;
3476
3477   if (height)
3478     *height = info ? info->default_height : -1;
3479 }
3480
3481 /**
3482  * gtk_window_resize:
3483  * @window: a #GtkWindow
3484  * @width: width in pixels to resize the window to
3485  * @height: height in pixels to resize the window to
3486  *
3487  * Resizes the window as if the user had done so, obeying geometry
3488  * constraints. The default geometry constraint is that windows may
3489  * not be smaller than their size request; to override this
3490  * constraint, call gtk_widget_set_size_request() to set the window's
3491  * request to a smaller value.
3492  *
3493  * If gtk_window_resize() is called before showing a window for the
3494  * first time, it overrides any default size set with
3495  * gtk_window_set_default_size().
3496  *
3497  * Windows may not be resized smaller than 1 by 1 pixels.
3498  * 
3499  **/
3500 void
3501 gtk_window_resize (GtkWindow *window,
3502                    gint       width,
3503                    gint       height)
3504 {
3505   GtkWindowGeometryInfo *info;
3506   
3507   g_return_if_fail (GTK_IS_WINDOW (window));
3508   g_return_if_fail (width > 0);
3509   g_return_if_fail (height > 0);
3510
3511   info = gtk_window_get_geometry_info (window, TRUE);
3512
3513   info->resize_width = width;
3514   info->resize_height = height;
3515
3516   gtk_widget_queue_resize (GTK_WIDGET (window));
3517 }
3518
3519 /**
3520  * gtk_window_get_size:
3521  * @window: a #GtkWindow
3522  * @width: return location for width, or %NULL
3523  * @height: return location for height, or %NULL
3524  *
3525  * Obtains the current size of @window. If @window is not onscreen,
3526  * it returns the size GTK+ will suggest to the <link
3527  * linkend="gtk-X11-arch">window manager</link> for the initial window
3528  * size (but this is not reliably the same as the size the window
3529  * manager will actually select). The size obtained by
3530  * gtk_window_get_size() is the last size received in a
3531  * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
3532  * rather than querying the X server for the size. As a result, if you
3533  * call gtk_window_resize() then immediately call
3534  * gtk_window_get_size(), the size won't have taken effect yet. After
3535  * the window manager processes the resize request, GTK+ receives
3536  * notification that the size has changed via a configure event, and
3537  * the size of the window gets updated.
3538  *
3539  * Note 1: Nearly any use of this function creates a race condition,
3540  * because the size of the window may change between the time that you
3541  * get the size and the time that you perform some action assuming
3542  * that size is the current size. To avoid race conditions, connect to
3543  * "configure_event" on the window and adjust your size-dependent
3544  * state to match the size delivered in the #GdkEventConfigure.
3545  *
3546  * Note 2: The returned size does <emphasis>not</emphasis> include the
3547  * size of the window manager decorations (aka the window frame or
3548  * border). Those are not drawn by GTK+ and GTK+ has no reliable
3549  * method of determining their size.
3550  *
3551  * Note 3: If you are getting a window size in order to position
3552  * the window onscreen, there may be a better way. The preferred
3553  * way is to simply set the window's semantic type with
3554  * gtk_window_set_type_hint(), which allows the window manager to
3555  * e.g. center dialogs. Also, if you set the transient parent of
3556  * dialogs with gtk_window_set_transient_for() window managers
3557  * will often center the dialog over its parent window. It's
3558  * much preferred to let the window manager handle these
3559  * things rather than doing it yourself, because all apps will
3560  * behave consistently and according to user prefs if the window
3561  * manager handles it. Also, the window manager can take the size
3562  * of the window decorations/border into account, while your
3563  * application cannot.
3564  *
3565  * In any case, if you insist on application-specified window
3566  * positioning, there's <emphasis>still</emphasis> a better way than
3567  * doing it yourself - gtk_window_set_position() will frequently
3568  * handle the details for you.
3569  * 
3570  **/
3571 void
3572 gtk_window_get_size (GtkWindow *window,
3573                      gint      *width,
3574                      gint      *height)
3575 {
3576   gint w, h;
3577   
3578   g_return_if_fail (GTK_IS_WINDOW (window));
3579
3580   if (width == NULL && height == NULL)
3581     return;
3582
3583   if (GTK_WIDGET_MAPPED (window))
3584     {
3585       gdk_drawable_get_size (GTK_WIDGET (window)->window,
3586                              &w, &h);
3587     }
3588   else
3589     {
3590       GdkRectangle configure_request;
3591
3592       gtk_window_compute_configure_request (window,
3593                                             &configure_request,
3594                                             NULL, NULL);
3595
3596       w = configure_request.width;
3597       h = configure_request.height;
3598     }
3599   
3600   if (width)
3601     *width = w;
3602   if (height)
3603     *height = h;
3604 }
3605
3606 /**
3607  * gtk_window_move:
3608  * @window: a #GtkWindow
3609  * @x: X coordinate to move window to
3610  * @y: Y coordinate to move window to
3611  *
3612  * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
3613  * @window to the given position.  Window managers are free to ignore
3614  * this; most window managers ignore requests for initial window
3615  * positions (instead using a user-defined placement algorithm) and
3616  * honor requests after the window has already been shown.
3617  *
3618  * Note: the position is the position of the gravity-determined
3619  * reference point for the window. The gravity determines two things:
3620  * first, the location of the reference point in root window
3621  * coordinates; and second, which point on the window is positioned at
3622  * the reference point.
3623  *
3624  * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
3625  * point is simply the @x, @y supplied to gtk_window_move(). The
3626  * top-left corner of the window decorations (aka window frame or
3627  * border) will be placed at @x, @y.  Therefore, to position a window
3628  * at the top left of the screen, you want to use the default gravity
3629  * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
3630  *
3631  * To position a window at the bottom right corner of the screen, you
3632  * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
3633  * point is at @x + the window width and @y + the window height, and
3634  * the bottom-right corner of the window border will be placed at that
3635  * reference point. So, to place a window in the bottom right corner
3636  * you would first set gravity to south east, then write:
3637  * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
3638  * gdk_screen_height () - window_height)</literal>.
3639  *
3640  * The Extended Window Manager Hints specification at <ulink 
3641  * url="http://www.freedesktop.org/Standards/wm-spec">
3642  * http://www.freedesktop.org/Standards/wm-spec</ulink> has a 
3643  * nice table of gravities in the "implementation notes" section.
3644  *
3645  * The gtk_window_get_position() documentation may also be relevant.
3646  * 
3647  **/
3648 void
3649 gtk_window_move (GtkWindow *window,
3650                  gint       x,
3651                  gint       y)
3652 {
3653   GtkWindowGeometryInfo *info;
3654   GtkWidget *widget;
3655   
3656   g_return_if_fail (GTK_IS_WINDOW (window));
3657
3658   widget = GTK_WIDGET (window);
3659
3660   info = gtk_window_get_geometry_info (window, TRUE);  
3661   
3662   if (GTK_WIDGET_MAPPED (window))
3663     {
3664       /* we have now sent a request with this position
3665        * with currently-active constraints, so toggle flag.
3666        */
3667       info->position_constraints_changed = FALSE;
3668
3669       /* we only constrain if mapped - if not mapped,
3670        * then gtk_window_compute_configure_request()
3671        * will apply the constraints later, and we
3672        * don't want to lose information about
3673        * what position the user set before then.
3674        * i.e. if you do a move() then turn off POS_CENTER
3675        * then show the window, your move() will work.
3676        */
3677       gtk_window_constrain_position (window,
3678                                      widget->allocation.width,
3679                                      widget->allocation.height,
3680                                      &x, &y);
3681       
3682       /* Note that this request doesn't go through our standard request
3683        * framework, e.g. doesn't increment configure_request_count,
3684        * doesn't set info->last, etc.; that's because
3685        * we don't save the info needed to arrive at this same request
3686        * again.
3687        *
3688        * To gtk_window_move_resize(), this will end up looking exactly
3689        * the same as the position being changed by the window
3690        * manager.
3691        */
3692       
3693       /* FIXME are we handling gravity properly for framed windows? */
3694       if (window->frame)
3695         gdk_window_move (window->frame,
3696                          x - window->frame_left,
3697                          y - window->frame_top);
3698       else
3699         gdk_window_move (GTK_WIDGET (window)->window,
3700                          x, y);
3701     }
3702   else
3703     {
3704       /* Save this position to apply on mapping */
3705       info->initial_x = x;
3706       info->initial_y = y;
3707       info->initial_pos_set = TRUE;
3708     }
3709 }
3710
3711 /**
3712  * gtk_window_get_position:
3713  * @window: a #GtkWindow
3714  * @root_x: return location for X coordinate of gravity-determined reference p\oint
3715  * @root_y: return location for Y coordinate of gravity-determined reference p\oint
3716  *
3717  * This function returns the position you need to pass to
3718  * gtk_window_move() to keep @window in its current position.  This
3719  * means that the meaning of the returned value varies with window
3720  * gravity. See gtk_window_move() for more details.
3721  * 
3722  * If you haven't changed the window gravity, its gravity will be
3723  * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
3724  * gets the position of the top-left corner of the window manager
3725  * frame for the window. gtk_window_move() sets the position of this
3726  * same top-left corner.
3727  *
3728  * gtk_window_get_position() is not 100% reliable because the X Window System
3729  * does not specify a way to obtain the geometry of the
3730  * decorations placed on a window by the window manager.
3731  * Thus GTK+ is using a "best guess" that works with most
3732  * window managers.
3733  *
3734  * Moreover, nearly all window managers are historically broken with
3735  * respect to their handling of window gravity. So moving a window to
3736  * its current position as returned by gtk_window_get_position() tends
3737  * to result in moving the window slightly. Window managers are
3738  * slowly getting better over time.
3739  *
3740  * If a window has gravity #GDK_GRAVITY_STATIC the window manager
3741  * frame is not relevant, and thus gtk_window_get_position() will
3742  * always produce accurate results. However you can't use static
3743  * gravity to do things like place a window in a corner of the screen,
3744  * because static gravity ignores the window manager decorations.
3745  *
3746  * If you are saving and restoring your application's window
3747  * positions, you should know that it's impossible for applications to
3748  * do this without getting it somewhat wrong because applications do
3749  * not have sufficient knowledge of window manager state. The Correct
3750  * Mechanism is to support the session management protocol (see the
3751  * "GnomeClient" object in the GNOME libraries for example) and allow
3752  * the window manager to save your window sizes and positions.
3753  * 
3754  **/
3755
3756 void
3757 gtk_window_get_position (GtkWindow *window,
3758                          gint      *root_x,
3759                          gint      *root_y)
3760 {
3761   GtkWidget *widget;
3762
3763   g_return_if_fail (GTK_IS_WINDOW (window));
3764
3765   widget = GTK_WIDGET (window);
3766   
3767   if (window->gravity == GDK_GRAVITY_STATIC)
3768     {
3769       if (GTK_WIDGET_MAPPED (widget))
3770         {
3771           /* This does a server round-trip, which is sort of wrong;
3772            * but a server round-trip is inevitable for
3773            * gdk_window_get_frame_extents() in the usual
3774            * NorthWestGravity case below, so not sure what else to
3775            * do. We should likely be consistent about whether we get
3776            * the client-side info or the server-side info.
3777            */
3778           gdk_window_get_origin (widget->window, root_x, root_y);
3779         }
3780       else
3781         {
3782           GdkRectangle configure_request;
3783           
3784           gtk_window_compute_configure_request (window,
3785                                                 &configure_request,
3786                                                 NULL, NULL);
3787           
3788           *root_x = configure_request.x;
3789           *root_y = configure_request.y;
3790         }
3791     }
3792   else
3793     {
3794       GdkRectangle frame_extents;
3795       
3796       gint x, y;
3797       gint w, h;
3798       
3799       if (GTK_WIDGET_MAPPED (widget))
3800         {
3801           if (window->frame)
3802             gdk_window_get_frame_extents (window->frame, &frame_extents);
3803           else
3804             gdk_window_get_frame_extents (widget->window, &frame_extents);
3805           x = frame_extents.x;
3806           y = frame_extents.y;
3807           gtk_window_get_size (window, &w, &h);
3808         }
3809       else
3810         {
3811           /* We just say the frame has 0 size on all sides.
3812            * Not sure what else to do.
3813            */             
3814           gtk_window_compute_configure_request (window,
3815                                                 &frame_extents,
3816                                                 NULL, NULL);
3817           x = frame_extents.x;
3818           y = frame_extents.y;
3819           w = frame_extents.width;
3820           h = frame_extents.height;
3821         }
3822       
3823       switch (window->gravity)
3824         {
3825         case GDK_GRAVITY_NORTH:
3826         case GDK_GRAVITY_CENTER:
3827         case GDK_GRAVITY_SOUTH:
3828           /* Find center of frame. */
3829           x += frame_extents.width / 2;
3830           /* Center client window on that point. */
3831           x -= w / 2;
3832           break;
3833
3834         case GDK_GRAVITY_SOUTH_EAST:
3835         case GDK_GRAVITY_EAST:
3836         case GDK_GRAVITY_NORTH_EAST:
3837           /* Find right edge of frame */
3838           x += frame_extents.width;
3839           /* Align left edge of client at that point. */
3840           x -= w;
3841           break;
3842         default:
3843           break;
3844         }
3845
3846       switch (window->gravity)
3847         {
3848         case GDK_GRAVITY_WEST:
3849         case GDK_GRAVITY_CENTER:
3850         case GDK_GRAVITY_EAST:
3851           /* Find center of frame. */
3852           y += frame_extents.height / 2;
3853           /* Center client window there. */
3854           y -= h / 2;
3855           break;
3856         case GDK_GRAVITY_SOUTH_WEST:
3857         case GDK_GRAVITY_SOUTH:
3858         case GDK_GRAVITY_SOUTH_EAST:
3859           /* Find south edge of frame */
3860           y += frame_extents.height;
3861           /* Place bottom edge of client there */
3862           y -= h;
3863           break;
3864         default:
3865           break;
3866         }
3867       
3868       if (root_x)
3869         *root_x = x;
3870       if (root_y)
3871         *root_y = y;
3872     }
3873 }
3874
3875 /**
3876  * gtk_window_reshow_with_initial_size:
3877  * @window: a #GtkWindow
3878  * 
3879  * Hides @window, then reshows it, resetting the
3880  * default size and position of the window. Used
3881  * by GUI builders only.
3882  **/
3883 void
3884 gtk_window_reshow_with_initial_size (GtkWindow *window)
3885 {
3886   GtkWidget *widget;
3887   
3888   g_return_if_fail (GTK_IS_WINDOW (window));
3889
3890   widget = GTK_WIDGET (window);
3891   
3892   gtk_widget_hide (widget);
3893   gtk_widget_unrealize (widget);
3894   gtk_widget_show (widget);
3895 }
3896
3897 static void
3898 gtk_window_destroy (GtkObject *object)
3899 {
3900   GtkWindow *window = GTK_WINDOW (object);
3901   
3902   toplevel_list = g_slist_remove (toplevel_list, window);
3903
3904   if (window->transient_parent)
3905     gtk_window_set_transient_for (window, NULL);
3906
3907   /* frees the icons */
3908   gtk_window_set_icon_list (window, NULL);
3909   
3910   if (window->has_user_ref_count)
3911     {
3912       window->has_user_ref_count = FALSE;
3913       g_object_unref (window);
3914     }
3915
3916   if (window->group)
3917     gtk_window_group_remove_window (window->group, window);
3918
3919    gtk_window_free_key_hash (window);
3920
3921    GTK_OBJECT_CLASS (parent_class)->destroy (object);
3922 }
3923
3924 static void
3925 gtk_window_finalize (GObject *object)
3926 {
3927   GtkWindow *window = GTK_WINDOW (object);
3928   GtkMnemonicHash *mnemonic_hash;
3929
3930   g_free (window->title);
3931   g_free (window->wmclass_name);
3932   g_free (window->wmclass_class);
3933   g_free (window->wm_role);
3934
3935   mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
3936   if (mnemonic_hash)
3937     _gtk_mnemonic_hash_free (mnemonic_hash);
3938
3939   if (window->geometry_info)
3940     {
3941       if (window->geometry_info->widget)
3942         g_signal_handlers_disconnect_by_func (window->geometry_info->widget,
3943                                               gtk_widget_destroyed,
3944                                               &window->geometry_info->widget);
3945       g_free (window->geometry_info);
3946     }
3947
3948   if (window->keys_changed_handler)
3949     {
3950       g_source_remove (window->keys_changed_handler);
3951       window->keys_changed_handler = 0;
3952     }
3953
3954   G_OBJECT_CLASS (parent_class)->finalize (object);
3955 }
3956
3957 static void
3958 gtk_window_show (GtkWidget *widget)
3959 {
3960   GtkWindow *window = GTK_WINDOW (widget);
3961   GtkContainer *container = GTK_CONTAINER (window);
3962   gboolean need_resize;
3963
3964   GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
3965   
3966   need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
3967   container->need_resize = FALSE;
3968
3969   if (need_resize)
3970     {
3971       GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
3972       GtkAllocation allocation = { 0, 0 };
3973       GdkRectangle configure_request;
3974       GdkGeometry new_geometry;
3975       guint new_flags;
3976       gboolean was_realized;
3977
3978       /* We are going to go ahead and perform this configure request
3979        * and then emulate a configure notify by going ahead and
3980        * doing a size allocate. Sort of a synchronous
3981        * mini-copy of gtk_window_move_resize() here.
3982        */
3983       gtk_window_compute_configure_request (window,
3984                                             &configure_request,
3985                                             &new_geometry,
3986                                             &new_flags);
3987       
3988       /* We update this because we are going to go ahead
3989        * and gdk_window_resize() below, rather than
3990        * queuing it.
3991        */
3992       info->last.configure_request.width = configure_request.width;
3993       info->last.configure_request.height = configure_request.height;
3994       
3995       /* and allocate the window - this is normally done
3996        * in move_resize in response to configure notify
3997        */
3998       allocation.width  = configure_request.width;
3999       allocation.height = configure_request.height;
4000       gtk_widget_size_allocate (widget, &allocation);
4001
4002       /* Then we guarantee we have a realize */
4003       was_realized = FALSE;
4004       if (!GTK_WIDGET_REALIZED (widget))
4005         {
4006           gtk_widget_realize (widget);
4007           was_realized = TRUE;
4008         }
4009
4010       /* Must be done after the windows are realized,
4011        * so that the decorations can be read
4012        */
4013       gtk_decorated_window_calculate_frame_size (window);
4014
4015       /* We only send configure request if we didn't just finish
4016        * creating the window; if we just created the window
4017        * then we created it with widget->allocation anyhow.
4018        */
4019       if (!was_realized)
4020         gdk_window_move_resize (widget->window,
4021                                 configure_request.x,
4022                                 configure_request.y,
4023                                 configure_request.width,
4024                                 configure_request.height);
4025     }
4026   
4027   gtk_container_check_resize (container);
4028
4029   gtk_widget_map (widget);
4030
4031   /* Try to make sure that we have some focused widget
4032    */
4033   if (!window->focus_widget && !GTK_IS_PLUG (window))
4034     gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD);
4035   
4036   if (window->modal)
4037     gtk_grab_add (widget);
4038 }
4039
4040 static void
4041 gtk_window_hide (GtkWidget *widget)
4042 {
4043   GtkWindow *window = GTK_WINDOW (widget);
4044
4045   GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
4046   gtk_widget_unmap (widget);
4047
4048   if (window->modal)
4049     gtk_grab_remove (widget);
4050 }
4051
4052 static void
4053 gtk_window_map (GtkWidget *widget)
4054 {
4055   GtkWindow *window = GTK_WINDOW (widget);
4056   GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
4057   GdkWindow *toplevel;
4058
4059   GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
4060
4061   if (window->bin.child &&
4062       GTK_WIDGET_VISIBLE (window->bin.child) &&
4063       !GTK_WIDGET_MAPPED (window->bin.child))
4064     gtk_widget_map (window->bin.child);
4065
4066   if (window->frame)
4067     toplevel = window->frame;
4068   else
4069     toplevel = widget->window;
4070   
4071   if (window->maximize_initially)
4072     gdk_window_maximize (toplevel);
4073   else
4074     gdk_window_unmaximize (toplevel);
4075   
4076   if (window->stick_initially)
4077     gdk_window_stick (toplevel);
4078   else
4079     gdk_window_unstick (toplevel);
4080   
4081   if (window->iconify_initially)
4082     gdk_window_iconify (toplevel);
4083   else
4084     gdk_window_deiconify (toplevel);
4085
4086   if (priv->fullscreen_initially)
4087     gdk_window_fullscreen (toplevel);
4088   else
4089     gdk_window_unfullscreen (toplevel);
4090   
4091   gdk_window_set_keep_above (toplevel, priv->above_initially);
4092
4093   gdk_window_set_keep_below (toplevel, priv->below_initially);
4094
4095   /* No longer use the default settings */
4096   window->need_default_size = FALSE;
4097   window->need_default_position = FALSE;
4098   
4099   gdk_window_show (widget->window);
4100
4101   if (window->frame)
4102     gdk_window_show (window->frame);
4103
4104   if (!disable_startup_notification &&
4105       !sent_startup_notification)
4106     {
4107       sent_startup_notification = TRUE;
4108       gdk_notify_startup_complete ();
4109     }
4110 }
4111
4112 static gboolean
4113 gtk_window_map_event (GtkWidget   *widget,
4114                       GdkEventAny *event)
4115 {
4116   if (!GTK_WIDGET_MAPPED (widget))
4117     {
4118       /* we should be be unmapped, but are getting a MapEvent, this may happen
4119        * to toplevel XWindows if mapping was intercepted by a window manager
4120        * and an unmap request occoured while the MapRequestEvent was still
4121        * being handled. we work around this situaiton here by re-requesting
4122        * the window being unmapped. more details can be found in:
4123        *   http://bugzilla.gnome.org/show_bug.cgi?id=316180
4124        */
4125       gdk_window_hide (widget->window);
4126     }
4127   return FALSE;
4128 }
4129
4130 static void
4131 gtk_window_unmap (GtkWidget *widget)
4132 {
4133   GtkWindow *window = GTK_WINDOW (widget);
4134   GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (widget);
4135   GtkWindowGeometryInfo *info;    
4136   GdkWindowState state;
4137
4138   GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
4139   if (window->frame)
4140     gdk_window_withdraw (window->frame);
4141   else 
4142     gdk_window_withdraw (widget->window);
4143   
4144   window->configure_request_count = 0;
4145   window->configure_notify_received = FALSE;
4146
4147   /* on unmap, we reset the default positioning of the window,
4148    * so it's placed again, but we don't reset the default
4149    * size of the window, so it's remembered.
4150    */
4151   window->need_default_position = TRUE;
4152
4153   info = gtk_window_get_geometry_info (window, FALSE);
4154   if (info)
4155     {
4156       info->initial_pos_set = FALSE;
4157       info->position_constraints_changed = FALSE;
4158     }
4159
4160   state = gdk_window_get_state (widget->window);
4161   window->iconify_initially = state & GDK_WINDOW_STATE_ICONIFIED;
4162   window->maximize_initially = state & GDK_WINDOW_STATE_MAXIMIZED;
4163   window->stick_initially = state & GDK_WINDOW_STATE_STICKY;
4164   priv->above_initially = state & GDK_WINDOW_STATE_ABOVE;
4165   priv->below_initially = state & GDK_WINDOW_STATE_BELOW;
4166 }
4167
4168 static void
4169 gtk_window_realize (GtkWidget *widget)
4170 {
4171   GtkWindow *window;
4172   GdkWindow *parent_window;
4173   GdkWindowAttr attributes;
4174   gint attributes_mask;
4175   GtkWindowPrivate *priv;
4176   
4177   window = GTK_WINDOW (widget);
4178
4179   priv = GTK_WINDOW_GET_PRIVATE (window);
4180
4181   /* ensure widget tree is properly size allocated */
4182   if (widget->allocation.x == -1 &&
4183       widget->allocation.y == -1 &&
4184       widget->allocation.width == 1 &&
4185       widget->allocation.height == 1)
4186     {
4187       GtkRequisition requisition;
4188       GtkAllocation allocation = { 0, 0, 200, 200 };
4189
4190       gtk_widget_size_request (widget, &requisition);
4191       if (requisition.width || requisition.height)
4192         {
4193           /* non-empty window */
4194           allocation.width = requisition.width;
4195           allocation.height = requisition.height;
4196         }
4197       gtk_widget_size_allocate (widget, &allocation);
4198       
4199       _gtk_container_queue_resize (GTK_CONTAINER (widget));
4200
4201       g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
4202     }
4203   
4204   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
4205   
4206   switch (window->type)
4207     {
4208     case GTK_WINDOW_TOPLEVEL:
4209       attributes.window_type = GDK_WINDOW_TOPLEVEL;
4210       break;
4211     case GTK_WINDOW_POPUP:
4212       attributes.window_type = GDK_WINDOW_TEMP;
4213       break;
4214     default:
4215       g_warning (G_STRLOC": Unknown window type %d!", window->type);
4216       break;
4217     }
4218    
4219   attributes.title = window->title;
4220   attributes.wmclass_name = window->wmclass_name;
4221   attributes.wmclass_class = window->wmclass_class;
4222   attributes.wclass = GDK_INPUT_OUTPUT;
4223   attributes.visual = gtk_widget_get_visual (widget);
4224   attributes.colormap = gtk_widget_get_colormap (widget);
4225
4226   if (window->has_frame)
4227     {
4228       attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
4229       attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
4230       attributes.event_mask = (GDK_EXPOSURE_MASK |
4231                                GDK_KEY_PRESS_MASK |
4232                                GDK_ENTER_NOTIFY_MASK |
4233                                GDK_LEAVE_NOTIFY_MASK |
4234                                GDK_FOCUS_CHANGE_MASK |
4235                                GDK_STRUCTURE_MASK |
4236                                GDK_BUTTON_MOTION_MASK |
4237                                GDK_POINTER_MOTION_HINT_MASK |
4238                                GDK_BUTTON_PRESS_MASK |
4239                                GDK_BUTTON_RELEASE_MASK);
4240       
4241       attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
4242       
4243       window->frame = gdk_window_new (gtk_widget_get_root_window (widget),
4244                                       &attributes, attributes_mask);
4245                                                  
4246       gdk_window_set_user_data (window->frame, widget);
4247       
4248       attributes.window_type = GDK_WINDOW_CHILD;
4249       attributes.x = window->frame_left;
4250       attributes.y = window->frame_top;
4251     
4252       attributes_mask = GDK_WA_X | GDK_WA_Y;
4253
4254       parent_window = window->frame;
4255     }
4256   else
4257     {
4258       attributes_mask = 0;
4259       parent_window = gtk_widget_get_root_window (widget);
4260     }
4261   
4262   attributes.width = widget->allocation.width;
4263   attributes.height = widget->allocation.height;
4264   attributes.event_mask = gtk_widget_get_events (widget);
4265   attributes.event_mask |= (GDK_EXPOSURE_MASK |
4266                             GDK_KEY_PRESS_MASK |
4267                             GDK_KEY_RELEASE_MASK |
4268                             GDK_ENTER_NOTIFY_MASK |
4269                             GDK_LEAVE_NOTIFY_MASK |
4270                             GDK_FOCUS_CHANGE_MASK |
4271                             GDK_STRUCTURE_MASK);
4272
4273   attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
4274   attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
4275   attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
4276   
4277   widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
4278
4279   gdk_window_enable_synchronized_configure (widget->window);
4280     
4281   gdk_window_set_user_data (widget->window, window);
4282       
4283   widget->style = gtk_style_attach (widget->style, widget->window);
4284   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
4285   if (window->frame)
4286     gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
4287
4288   /* This is a bad hack to set the window background. */
4289   gtk_window_paint (widget, NULL);
4290   
4291   if (window->transient_parent &&
4292       GTK_WIDGET_REALIZED (window->transient_parent))
4293     gdk_window_set_transient_for (widget->window,
4294                                   GTK_WIDGET (window->transient_parent)->window);
4295
4296   if (window->wm_role)
4297     gdk_window_set_role (widget->window, window->wm_role);
4298   
4299   if (!window->decorated)
4300     gdk_window_set_decorations (widget->window, 0);
4301
4302   if (!priv->deletable)
4303     gdk_window_set_functions (widget->window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
4304
4305   gdk_window_set_type_hint (widget->window, window->type_hint);
4306
4307   if (gtk_window_get_skip_pager_hint (window))
4308     gdk_window_set_skip_pager_hint (widget->window, TRUE);
4309
4310   if (gtk_window_get_skip_taskbar_hint (window))
4311     gdk_window_set_skip_taskbar_hint (widget->window, TRUE);
4312
4313   if (gtk_window_get_accept_focus (window))
4314     gdk_window_set_accept_focus (widget->window, TRUE);
4315   else
4316     gdk_window_set_accept_focus (widget->window, FALSE);
4317
4318   if (gtk_window_get_focus_on_map (window))
4319     gdk_window_set_focus_on_map (widget->window, TRUE);
4320   else
4321     gdk_window_set_focus_on_map (widget->window, FALSE);
4322   
4323   if (window->modal)
4324     gdk_window_set_modal_hint (widget->window, TRUE);
4325   else
4326     gdk_window_set_modal_hint (widget->window, FALSE);
4327
4328   /* Icons */
4329   gtk_window_realize_icon (window);
4330 }
4331
4332 static void
4333 gtk_window_unrealize (GtkWidget *widget)
4334 {
4335   GtkWindow *window;
4336   GtkWindowGeometryInfo *info;
4337
4338   window = GTK_WINDOW (widget);
4339
4340   /* On unrealize, we reset the size of the window such
4341    * that we will re-apply the default sizing stuff
4342    * next time we show the window.
4343    *
4344    * Default positioning is reset on unmap, instead of unrealize.
4345    */
4346   window->need_default_size = TRUE;
4347   info = gtk_window_get_geometry_info (window, FALSE);
4348   if (info)
4349     {
4350       info->resize_width = -1;
4351       info->resize_height = -1;
4352       info->last.configure_request.x = 0;
4353       info->last.configure_request.y = 0;
4354       info->last.configure_request.width = -1;
4355       info->last.configure_request.height = -1;
4356       /* be sure we reset geom hints on re-realize */
4357       info->last.flags = 0;
4358     }
4359   
4360   if (window->frame)
4361     {
4362       gdk_window_set_user_data (window->frame, NULL);
4363       gdk_window_destroy (window->frame);
4364       window->frame = NULL;
4365     }
4366
4367   /* Icons */
4368   gtk_window_unrealize_icon (window);
4369   
4370   (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
4371 }
4372
4373 static void
4374 gtk_window_size_request (GtkWidget      *widget,
4375                          GtkRequisition *requisition)
4376 {
4377   GtkWindow *window;
4378   GtkBin *bin;
4379
4380   window = GTK_WINDOW (widget);
4381   bin = GTK_BIN (window);
4382   
4383   requisition->width = GTK_CONTAINER (window)->border_width * 2;
4384   requisition->height = GTK_CONTAINER (window)->border_width * 2;
4385
4386   if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
4387     {
4388       GtkRequisition child_requisition;
4389       
4390       gtk_widget_size_request (bin->child, &child_requisition);
4391
4392       requisition->width += child_requisition.width;
4393       requisition->height += child_requisition.height;
4394     }
4395 }
4396
4397 static void
4398 gtk_window_size_allocate (GtkWidget     *widget,
4399                           GtkAllocation *allocation)
4400 {
4401   GtkWindow *window;
4402   GtkAllocation child_allocation;
4403
4404   window = GTK_WINDOW (widget);
4405   widget->allocation = *allocation;
4406
4407   if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
4408     {
4409       child_allocation.x = GTK_CONTAINER (window)->border_width;
4410       child_allocation.y = GTK_CONTAINER (window)->border_width;
4411       child_allocation.width =
4412         MAX (1, (gint)allocation->width - child_allocation.x * 2);
4413       child_allocation.height =
4414         MAX (1, (gint)allocation->height - child_allocation.y * 2);
4415
4416       gtk_widget_size_allocate (window->bin.child, &child_allocation);
4417     }
4418
4419   if (GTK_WIDGET_REALIZED (widget) && window->frame)
4420     {
4421       gdk_window_resize (window->frame,
4422                          allocation->width + window->frame_left + window->frame_right,
4423                          allocation->height + window->frame_top + window->frame_bottom);
4424     }
4425 }
4426
4427 static gint
4428 gtk_window_event (GtkWidget *widget, GdkEvent *event)
4429 {
4430   GtkWindow *window;
4431   gboolean return_val;
4432
4433   window = GTK_WINDOW (widget);
4434
4435   if (window->frame && (event->any.window == window->frame))
4436     {
4437       if ((event->type != GDK_KEY_PRESS) &&
4438           (event->type != GDK_KEY_RELEASE) &&
4439           (event->type != GDK_FOCUS_CHANGE))
4440         {
4441           g_signal_stop_emission_by_name (widget, "event");
4442           return_val = FALSE;
4443           g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
4444           return TRUE;
4445         }
4446       else
4447         {
4448           g_object_unref (event->any.window);
4449           event->any.window = g_object_ref (widget->window);
4450         }
4451     }
4452
4453   return FALSE;
4454 }
4455
4456 static gboolean
4457 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
4458 {
4459   GdkEventConfigure *configure_event;
4460   GdkRectangle rect;
4461
4462   switch (event->type)
4463     {
4464     case GDK_CONFIGURE:
4465       configure_event = (GdkEventConfigure *)event;
4466       
4467       /* Invalidate the decorations */
4468       rect.x = 0;
4469       rect.y = 0;
4470       rect.width = configure_event->width;
4471       rect.height = configure_event->height;
4472       
4473       gdk_window_invalidate_rect (window->frame, &rect, FALSE);
4474
4475       /* Pass on the (modified) configure event */
4476       configure_event->width -= window->frame_left + window->frame_right;
4477       configure_event->height -= window->frame_top + window->frame_bottom;
4478       return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
4479       break;
4480     default:
4481       break;
4482     }
4483   return FALSE;
4484 }
4485
4486 static gint
4487 gtk_window_configure_event (GtkWidget         *widget,
4488                             GdkEventConfigure *event)
4489 {
4490   GtkWindow *window = GTK_WINDOW (widget);
4491   gboolean expected_reply = window->configure_request_count > 0;
4492
4493   /* window->configure_request_count incremented for each 
4494    * configure request, and decremented to a min of 0 for
4495    * each configure notify.
4496    *
4497    * All it means is that we know we will get at least
4498    * window->configure_request_count more configure notifies.
4499    * We could get more configure notifies than that; some
4500    * of the configure notifies we get may be unrelated to
4501    * the configure requests. But we will get at least
4502    * window->configure_request_count notifies.
4503    */
4504
4505   if (window->configure_request_count > 0)
4506     window->configure_request_count -= 1;
4507   
4508   /* As an optimization, we avoid a resize when possible.
4509    *
4510    * The only times we can avoid a resize are:
4511    *   - we know only the position changed, not the size
4512    *   - we know we have made more requests and so will get more
4513    *     notifies and can wait to resize when we get them
4514    */
4515   
4516   if (!expected_reply &&
4517       (widget->allocation.width == event->width &&
4518        widget->allocation.height == event->height))
4519     {
4520       gdk_window_configure_finished (widget->window);
4521       return TRUE;
4522     }
4523
4524   /*
4525    * If we do need to resize, we do that by:
4526    *   - filling in widget->allocation with the new size
4527    *   - setting configure_notify_received to TRUE
4528    *     for use in gtk_window_move_resize()
4529    *   - queueing a resize, leading to invocation of
4530    *     gtk_window_move_resize() in an idle handler
4531    *
4532    */
4533   
4534   window->configure_notify_received = TRUE;
4535   
4536   widget->allocation.width = event->width;
4537   widget->allocation.height = event->height;
4538   
4539   _gtk_container_queue_resize (GTK_CONTAINER (widget));
4540   
4541   return TRUE;
4542 }
4543
4544 /* the accel_key and accel_mods fields of the key have to be setup
4545  * upon calling this function. it'll then return whether that key
4546  * is at all used as accelerator, and if so will OR in the
4547  * accel_flags member of the key.
4548  */
4549 gboolean
4550 _gtk_window_query_nonaccels (GtkWindow      *window,
4551                              guint           accel_key,
4552                              GdkModifierType accel_mods)
4553 {
4554   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4555
4556   /* movement keys are considered locked accels */
4557   if (!accel_mods)
4558     {
4559       static const guint bindings[] = {
4560         GDK_space, GDK_KP_Space, GDK_Return, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
4561         GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
4562       };
4563       guint i;
4564       
4565       for (i = 0; i < G_N_ELEMENTS (bindings); i++)
4566         if (bindings[i] == accel_key)
4567           return TRUE;
4568     }
4569
4570   /* mnemonics are considered locked accels */
4571   if (accel_mods == window->mnemonic_modifier)
4572     {
4573       GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4574       if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
4575         return TRUE;
4576     }
4577
4578   return FALSE;
4579 }
4580
4581 /**
4582  * gtk_window_propagate_key_event:
4583  * @window:  a #GtkWindow
4584  * @event:   a #GdkEventKey
4585  *
4586  * Propagate a key press or release event to the focus widget and
4587  * up the focus container chain until a widget handles @event.
4588  * This is normally called by the default ::key_press_event and
4589  * ::key_release_event handlers for toplevel windows,
4590  * however in some cases it may be useful to call this directly when
4591  * overriding the standard key handling for a toplevel window.
4592  *
4593  * Return value: %TRUE if a widget in the focus chain handled the event.
4594  **/
4595 gboolean
4596 gtk_window_propagate_key_event (GtkWindow        *window,
4597                                 GdkEventKey      *event)
4598 {
4599   gboolean handled = FALSE;
4600   GtkWidget *widget, *focus;
4601
4602   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4603
4604   widget = GTK_WIDGET (window);
4605   focus = window->focus_widget;
4606   if (focus)
4607     g_object_ref (focus);
4608   
4609   while (!handled &&
4610          focus && focus != widget &&
4611          gtk_widget_get_toplevel (focus) == widget)
4612     {
4613       GtkWidget *parent;
4614       
4615       if (GTK_WIDGET_IS_SENSITIVE (focus))
4616         handled = gtk_widget_event (focus, (GdkEvent*) event);
4617       
4618       parent = focus->parent;
4619       if (parent)
4620         g_object_ref (parent);
4621       
4622       g_object_unref (focus);
4623       
4624       focus = parent;
4625     }
4626   
4627   if (focus)
4628     g_object_unref (focus);
4629
4630   return handled;
4631 }
4632
4633 static gint
4634 gtk_window_key_press_event (GtkWidget   *widget,
4635                             GdkEventKey *event)
4636 {
4637   GtkWindow *window = GTK_WINDOW (widget);
4638   gboolean handled = FALSE;
4639
4640   /* handle mnemonics and accelerators */
4641   if (!handled)
4642     handled = gtk_window_activate_key (window, event);
4643
4644   /* handle focus widget key events */
4645   if (!handled)
4646     handled = gtk_window_propagate_key_event (window, event);
4647
4648   /* Chain up, invokes binding set */
4649   if (!handled)
4650     handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
4651
4652   return handled;
4653 }
4654
4655 static gint
4656 gtk_window_key_release_event (GtkWidget   *widget,
4657                               GdkEventKey *event)
4658 {
4659   GtkWindow *window = GTK_WINDOW (widget);
4660   gboolean handled = FALSE;
4661
4662   /* handle focus widget key events */
4663   if (!handled)
4664     handled = gtk_window_propagate_key_event (window, event);
4665
4666   /* Chain up, invokes binding set */
4667   if (!handled)
4668     handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
4669
4670   return handled;
4671 }
4672
4673 static void
4674 gtk_window_real_activate_default (GtkWindow *window)
4675 {
4676   gtk_window_activate_default (window);
4677 }
4678
4679 static void
4680 gtk_window_real_activate_focus (GtkWindow *window)
4681 {
4682   gtk_window_activate_focus (window);
4683 }
4684
4685 static void
4686 gtk_window_move_focus (GtkWindow       *window,
4687                        GtkDirectionType dir)
4688 {
4689   gtk_widget_child_focus (GTK_WIDGET (window), dir);
4690   
4691   if (!GTK_CONTAINER (window)->focus_child)
4692     gtk_window_set_focus (window, NULL);
4693 }
4694
4695 static gint
4696 gtk_window_enter_notify_event (GtkWidget        *widget,
4697                                GdkEventCrossing *event)
4698 {
4699   return FALSE;
4700 }
4701
4702 static gint
4703 gtk_window_leave_notify_event (GtkWidget        *widget,
4704                                GdkEventCrossing *event)
4705 {
4706   return FALSE;
4707 }
4708
4709 static void
4710 do_focus_change (GtkWidget *widget,
4711                  gboolean   in)
4712 {
4713   GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
4714   
4715   g_object_ref (widget);
4716   
4717   if (in)
4718     GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
4719   else
4720     GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
4721   
4722   fevent->focus_change.type = GDK_FOCUS_CHANGE;
4723   fevent->focus_change.window = widget->window;
4724   if (widget->window)
4725     g_object_ref (widget->window);
4726   fevent->focus_change.in = in;
4727   
4728   gtk_widget_event (widget, fevent);
4729   
4730   g_object_notify (G_OBJECT (widget), "has-focus");
4731
4732   g_object_unref (widget);
4733   gdk_event_free (fevent);
4734 }
4735
4736 static gint
4737 gtk_window_focus_in_event (GtkWidget     *widget,
4738                            GdkEventFocus *event)
4739 {
4740   GtkWindow *window = GTK_WINDOW (widget);
4741
4742   /* It appears spurious focus in events can occur when
4743    *  the window is hidden. So we'll just check to see if
4744    *  the window is visible before actually handling the
4745    *  event
4746    */
4747   if (GTK_WIDGET_VISIBLE (widget))
4748     {
4749       _gtk_window_set_has_toplevel_focus (window, TRUE);
4750       _gtk_window_set_is_active (window, TRUE);
4751     }
4752       
4753   return FALSE;
4754 }
4755
4756 static gint
4757 gtk_window_focus_out_event (GtkWidget     *widget,
4758                             GdkEventFocus *event)
4759 {
4760   GtkWindow *window = GTK_WINDOW (widget);
4761
4762   _gtk_window_set_has_toplevel_focus (window, FALSE);
4763   _gtk_window_set_is_active (window, FALSE);
4764
4765   return FALSE;
4766 }
4767
4768 static GdkAtom atom_rcfiles = GDK_NONE;
4769 static GdkAtom atom_iconthemes = GDK_NONE;
4770
4771 static void
4772 send_client_message_to_embedded_windows (GtkWidget *widget,
4773                                          GdkAtom    message_type)
4774 {
4775   GList *embedded_windows;
4776
4777   embedded_windows = g_object_get_data (G_OBJECT (widget), "gtk-embedded");
4778   if (embedded_windows)
4779     {
4780       GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
4781       int i;
4782       
4783       for (i = 0; i < 5; i++)
4784         send_event->client.data.l[i] = 0;
4785       send_event->client.data_format = 32;
4786       send_event->client.message_type = message_type;
4787       
4788       while (embedded_windows)
4789         {
4790           guint xid = GPOINTER_TO_UINT (embedded_windows->data);
4791           gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
4792           embedded_windows = embedded_windows->next;
4793         }
4794
4795       gdk_event_free (send_event);
4796     }
4797 }
4798
4799 static gint
4800 gtk_window_client_event (GtkWidget      *widget,
4801                          GdkEventClient *event)
4802 {
4803   if (!atom_rcfiles)
4804     {
4805       atom_rcfiles = gdk_atom_intern_static_string ("_GTK_READ_RCFILES");
4806       atom_iconthemes = gdk_atom_intern_static_string ("_GTK_LOAD_ICONTHEMES");
4807     }
4808
4809   if (event->message_type == atom_rcfiles) 
4810     {
4811       send_client_message_to_embedded_windows (widget, atom_rcfiles);
4812       gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
4813     }
4814
4815   if (event->message_type == atom_iconthemes) 
4816     {
4817       send_client_message_to_embedded_windows (widget, atom_iconthemes);
4818       _gtk_icon_theme_check_reload (gtk_widget_get_display (widget));    
4819     }
4820
4821   return FALSE;
4822 }
4823
4824 static void
4825 gtk_window_check_resize (GtkContainer *container)
4826 {
4827   GtkWindow *window = GTK_WINDOW (container);
4828
4829   if (GTK_WIDGET_VISIBLE (container))
4830     gtk_window_move_resize (window);
4831 }
4832
4833 static gboolean
4834 gtk_window_focus (GtkWidget        *widget,
4835                   GtkDirectionType  direction)
4836 {
4837   GtkBin *bin;
4838   GtkWindow *window;
4839   GtkContainer *container;
4840   GtkWidget *old_focus_child;
4841   GtkWidget *parent;
4842
4843   container = GTK_CONTAINER (widget);
4844   window = GTK_WINDOW (widget);
4845   bin = GTK_BIN (widget);
4846
4847   old_focus_child = container->focus_child;
4848   
4849   /* We need a special implementation here to deal properly with wrapping
4850    * around in the tab chain without the danger of going into an
4851    * infinite loop.
4852    */
4853   if (old_focus_child)
4854     {
4855       if (gtk_widget_child_focus (old_focus_child, direction))
4856         return TRUE;
4857     }
4858
4859   if (window->focus_widget)
4860     {
4861       if (direction == GTK_DIR_LEFT ||
4862           direction == GTK_DIR_RIGHT ||
4863           direction == GTK_DIR_UP ||
4864           direction == GTK_DIR_DOWN)
4865         {
4866           return FALSE;
4867         }
4868       
4869       /* Wrapped off the end, clear the focus setting for the toplpevel */
4870       parent = window->focus_widget->parent;
4871       while (parent)
4872         {
4873           gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
4874           parent = GTK_WIDGET (parent)->parent;
4875         }
4876       
4877       gtk_window_set_focus (GTK_WINDOW (container), NULL);
4878     }
4879
4880   /* Now try to focus the first widget in the window */
4881   if (bin->child)
4882     {
4883       if (gtk_widget_child_focus (bin->child, direction))
4884         return TRUE;
4885     }
4886
4887   return FALSE;
4888 }
4889
4890 static void
4891 gtk_window_real_set_focus (GtkWindow *window,
4892                            GtkWidget *focus)
4893 {
4894   GtkWidget *old_focus = window->focus_widget;
4895   gboolean had_default = FALSE;
4896   gboolean focus_had_default = FALSE;
4897   gboolean old_focus_had_default = FALSE;
4898
4899   if (old_focus)
4900     {
4901       g_object_ref (old_focus);
4902       g_object_freeze_notify (G_OBJECT (old_focus));
4903       old_focus_had_default = GTK_WIDGET_HAS_DEFAULT (old_focus);
4904     }
4905   if (focus)
4906     {
4907       g_object_ref (focus);
4908       g_object_freeze_notify (G_OBJECT (focus));
4909       focus_had_default = GTK_WIDGET_HAS_DEFAULT (focus);
4910     }
4911   
4912   if (window->default_widget)
4913     had_default = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
4914   
4915   if (window->focus_widget)
4916     {
4917       if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4918           (window->focus_widget != window->default_widget))
4919         {
4920           GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
4921           gtk_widget_queue_draw (window->focus_widget);
4922           
4923           if (window->default_widget)
4924             GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
4925         }
4926
4927       window->focus_widget = NULL;
4928
4929       if (window->has_focus)
4930         do_focus_change (old_focus, FALSE);
4931
4932       g_object_notify (G_OBJECT (old_focus), "is-focus");
4933     }
4934
4935   /* The above notifications may have set a new focus widget,
4936    * if so, we don't want to override it.
4937    */
4938   if (focus && !window->focus_widget)
4939     {
4940       window->focus_widget = focus;
4941   
4942       if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4943           (window->focus_widget != window->default_widget))
4944         {
4945           if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
4946             GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
4947
4948           if (window->default_widget)
4949             GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
4950         }
4951
4952       if (window->has_focus)
4953         do_focus_change (window->focus_widget, TRUE);
4954
4955       g_object_notify (G_OBJECT (window->focus_widget), "is-focus");
4956     }
4957
4958   /* If the default widget changed, a redraw will have been queued
4959    * on the old and new default widgets by gtk_window_set_default(), so
4960    * we only have to worry about the case where it didn't change.
4961    * We'll sometimes queue a draw twice on the new widget but that
4962    * is harmless.
4963    */
4964   if (window->default_widget &&
4965       (had_default != GTK_WIDGET_HAS_DEFAULT (window->default_widget)))
4966     gtk_widget_queue_draw (window->default_widget);
4967   
4968   if (old_focus)
4969     {
4970       if (old_focus_had_default != GTK_WIDGET_HAS_DEFAULT (old_focus))
4971         gtk_widget_queue_draw (old_focus);
4972         
4973       g_object_thaw_notify (G_OBJECT (old_focus));
4974       g_object_unref (old_focus);
4975     }
4976   if (focus)
4977     {
4978       if (focus_had_default != GTK_WIDGET_HAS_DEFAULT (focus))
4979         gtk_widget_queue_draw (focus);
4980
4981       g_object_thaw_notify (G_OBJECT (focus));
4982       g_object_unref (focus);
4983     }
4984 }
4985
4986 /**
4987  * _gtk_window_unset_focus_and_default:
4988  * @window: a #GtkWindow
4989  * @widget: a widget inside of @window
4990  * 
4991  * Checks whether the focus and default widgets of @window are
4992  * @widget or a descendent of @widget, and if so, unset them.
4993  **/
4994 void
4995 _gtk_window_unset_focus_and_default (GtkWindow *window,
4996                                      GtkWidget *widget)
4997
4998 {
4999   GtkWidget *child;
5000
5001   g_object_ref (window);
5002   g_object_ref (widget);
5003       
5004   if (GTK_CONTAINER (widget->parent)->focus_child == widget)
5005     {
5006       child = window->focus_widget;
5007       
5008       while (child && child != widget)
5009         child = child->parent;
5010   
5011       if (child == widget)
5012         gtk_window_set_focus (GTK_WINDOW (window), NULL);
5013     }
5014       
5015   child = window->default_widget;
5016       
5017   while (child && child != widget)
5018     child = child->parent;
5019       
5020   if (child == widget)
5021     gtk_window_set_default (window, NULL);
5022   
5023   g_object_unref (widget);
5024   g_object_unref (window);
5025 }
5026
5027 /*********************************
5028  * Functions related to resizing *
5029  *********************************/
5030
5031 /* This function doesn't constrain to geometry hints */
5032 static void 
5033 gtk_window_compute_configure_request_size (GtkWindow *window,
5034                                            guint     *width,
5035                                            guint     *height)
5036 {
5037   GtkRequisition requisition;
5038   GtkWindowGeometryInfo *info;
5039   GtkWidget *widget;
5040
5041   /* Preconditions:
5042    *  - we've done a size request
5043    */
5044   
5045   widget = GTK_WIDGET (window);
5046
5047   info = gtk_window_get_geometry_info (window, FALSE);
5048   
5049   if (window->need_default_size)
5050     {
5051       gtk_widget_get_child_requisition (widget, &requisition);
5052
5053       /* Default to requisition */
5054       *width = requisition.width;
5055       *height = requisition.height;
5056
5057       /* If window is empty so requests 0, default to random nonzero size */
5058        if (*width == 0 && *height == 0)
5059          {
5060            *width = 200;
5061            *height = 200;
5062          }
5063
5064        /* Override requisition with default size */
5065
5066        if (info)
5067          {
5068            gint base_width = 0;
5069            gint base_height = 0;
5070            gint width_inc = 1;
5071            gint height_inc = 1;
5072            
5073            if (info->default_is_geometry &&
5074                (info->default_width > 0 || info->default_height > 0))
5075              {
5076                GdkGeometry geometry;
5077                guint flags;
5078                
5079                gtk_window_compute_hints (window, &geometry, &flags);
5080
5081                if (flags & GDK_HINT_BASE_SIZE)
5082                  {
5083                    base_width = geometry.base_width;
5084                    base_height = geometry.base_height;
5085                  }
5086                else if (flags & GDK_HINT_MIN_SIZE)
5087                  {
5088                    base_width = geometry.min_width;
5089                    base_height = geometry.min_height;
5090                  }
5091                if (flags & GDK_HINT_RESIZE_INC)
5092                  {
5093                    width_inc = geometry.width_inc;
5094                    height_inc = geometry.height_inc;
5095                  }
5096              }
5097              
5098            if (info->default_width > 0)
5099              *width = info->default_width * width_inc + base_width;
5100            
5101            if (info->default_height > 0)
5102              *height = info->default_height * height_inc + base_height;
5103          }
5104     }
5105   else
5106     {
5107       /* Default to keeping current size */
5108       *width = widget->allocation.width;
5109       *height = widget->allocation.height;
5110     }
5111
5112   /* Override any size with gtk_window_resize() values */
5113   if (info)
5114     {
5115       if (info->resize_width > 0)
5116         *width = info->resize_width;
5117
5118       if (info->resize_height > 0)
5119         *height = info->resize_height;
5120     }
5121 }
5122
5123 static GtkWindowPosition
5124 get_effective_position (GtkWindow *window)
5125 {
5126   GtkWindowPosition pos = window->position;
5127   if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
5128       (window->transient_parent == NULL ||
5129        !GTK_WIDGET_MAPPED (window->transient_parent)))
5130     pos = GTK_WIN_POS_NONE;
5131
5132   return pos;
5133 }
5134
5135 static int
5136 get_center_monitor_of_window (GtkWindow *window)
5137 {
5138   /* We could try to sort out the relative positions of the monitors and
5139    * stuff, or we could just be losers and assume you have a row
5140    * or column of monitors.
5141    */
5142   return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
5143 }
5144
5145 static int
5146 get_monitor_containing_pointer (GtkWindow *window)
5147 {
5148   gint px, py;
5149   gint monitor_num;
5150   GdkScreen *window_screen;
5151   GdkScreen *pointer_screen;
5152
5153   window_screen = gtk_window_check_screen (window);
5154   gdk_display_get_pointer (gdk_screen_get_display (window_screen),
5155                            &pointer_screen,
5156                            &px, &py, NULL);
5157
5158   if (pointer_screen == window_screen)
5159     monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
5160   else
5161     monitor_num = -1;
5162
5163   return monitor_num;
5164 }
5165
5166 static void
5167 center_window_on_monitor (GtkWindow *window,
5168                           gint       w,
5169                           gint       h,
5170                           gint      *x,
5171                           gint      *y)
5172 {
5173   GdkRectangle monitor;
5174   int monitor_num;
5175
5176   monitor_num = get_monitor_containing_pointer (window);
5177   
5178   if (monitor_num == -1)
5179     monitor_num = get_center_monitor_of_window (window);
5180
5181   gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
5182                                    monitor_num, &monitor);
5183   
5184   *x = (monitor.width - w) / 2 + monitor.x;
5185   *y = (monitor.height - h) / 2 + monitor.y;
5186
5187   /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
5188    * and WM decorations.
5189    */
5190   if (*x < monitor.x)
5191     *x = monitor.x;
5192   if (*y < monitor.y)
5193     *y = monitor.y;
5194 }
5195
5196 static void
5197 clamp_window_to_rectangle (gint               *x,
5198                            gint               *y,
5199                            gint                w,
5200                            gint                h,
5201                            const GdkRectangle *rect)
5202 {
5203   gint outside_w, outside_h;
5204   
5205   outside_w = (*x + w) - (rect->x + rect->width);
5206   if (outside_w > 0)
5207     *x -= outside_w;
5208
5209   outside_h = (*y + h) - (rect->y + rect->height);
5210   if (outside_h > 0)
5211     *y -= outside_h; 
5212
5213   /* if larger than the screen, center on the screen. */
5214   if (*x < rect->x)
5215     *x += (rect->x - *x) / 2;
5216   if (*y < rect->y)
5217     *y += (rect->y - *y) / 2;
5218 }
5219
5220
5221 static void
5222 gtk_window_compute_configure_request (GtkWindow    *window,
5223                                       GdkRectangle *request,
5224                                       GdkGeometry  *geometry,
5225                                       guint        *flags)
5226 {
5227   GdkGeometry new_geometry;
5228   guint new_flags;
5229   int w, h;
5230   GtkWidget *widget;
5231   GtkWindowPosition pos;
5232   GtkWidget *parent_widget;
5233   GtkWindowGeometryInfo *info;
5234   GdkScreen *screen;
5235   int x, y;
5236   
5237   widget = GTK_WIDGET (window);
5238
5239   screen = gtk_window_check_screen (window);
5240   
5241   gtk_widget_size_request (widget, NULL);
5242   gtk_window_compute_configure_request_size (window, (guint *)&w, (guint *)&h);
5243   
5244   gtk_window_compute_hints (window, &new_geometry, &new_flags);
5245   gtk_window_constrain_size (window,
5246                              &new_geometry, new_flags,
5247                              w, h,
5248                              &w, &h);
5249
5250   parent_widget = (GtkWidget*) window->transient_parent;
5251   
5252   pos = get_effective_position (window);
5253   info = gtk_window_get_geometry_info (window, TRUE);
5254
5255   /* by default, don't change position requested */
5256   x = info->last.configure_request.x;
5257   y = info->last.configure_request.y;
5258   
5259   if (window->need_default_position)
5260     {
5261
5262       /* FIXME this all interrelates with window gravity.
5263        * For most of them I think we want to set GRAVITY_CENTER.
5264        *
5265        * Not sure how to go about that.
5266        */
5267       
5268       switch (pos)
5269         {
5270           /* here we are only handling CENTER_ALWAYS
5271            * as it relates to default positioning,
5272            * where it's equivalent to simply CENTER
5273            */
5274         case GTK_WIN_POS_CENTER_ALWAYS:
5275         case GTK_WIN_POS_CENTER:
5276           center_window_on_monitor (window, w, h, &x, &y);
5277           break;
5278       
5279         case GTK_WIN_POS_CENTER_ON_PARENT:
5280           {
5281             gint monitor_num;
5282             GdkRectangle monitor;
5283             gint ox, oy;
5284             
5285             g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
5286
5287             if (parent_widget->window != NULL)
5288               monitor_num = gdk_screen_get_monitor_at_window (screen,
5289                                                               parent_widget->window);
5290             else
5291               monitor_num = -1;
5292             
5293             gdk_window_get_origin (parent_widget->window,
5294                                    &ox, &oy);
5295             
5296             x = ox + (parent_widget->allocation.width - w) / 2;
5297             y = oy + (parent_widget->allocation.height - h) / 2;
5298             
5299             /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
5300              * WM decorations. If parent wasn't on a monitor, just
5301              * give up.
5302              */
5303             if (monitor_num >= 0)
5304               {
5305                 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
5306                 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
5307               }
5308           }
5309           break;
5310
5311         case GTK_WIN_POS_MOUSE:
5312           {
5313             gint screen_width = gdk_screen_get_width (screen);
5314             gint screen_height = gdk_screen_get_height (screen);
5315             gint monitor_num;
5316             GdkRectangle monitor;
5317             GdkScreen *pointer_screen;
5318             gint px, py;
5319             
5320             gdk_display_get_pointer (gdk_screen_get_display (screen),
5321                                      &pointer_screen,
5322                                      &px, &py, NULL);
5323
5324             if (pointer_screen == screen)
5325               monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
5326             else
5327               monitor_num = -1;
5328             
5329             x = px - w / 2;
5330             y = py - h / 2;
5331             x = CLAMP (x, 0, screen_width - w);
5332             y = CLAMP (y, 0, screen_height - h);
5333
5334             /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
5335              * WM decorations. Don't try to figure out what's going
5336              * on if the mouse wasn't inside a monitor.
5337              */
5338             if (monitor_num >= 0)
5339               {
5340                 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
5341                 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
5342               }
5343           }
5344           break;
5345
5346         default:
5347           break;
5348         }
5349     } /* if (window->need_default_position) */
5350
5351   if (window->need_default_position &&
5352       info->initial_pos_set)
5353     {
5354       x = info->initial_x;
5355       y = info->initial_y;
5356       gtk_window_constrain_position (window, w, h, &x, &y);
5357     }
5358   
5359   request->x = x;
5360   request->y = y;
5361   request->width = w;
5362   request->height = h;
5363
5364   if (geometry)
5365     *geometry = new_geometry;
5366   if (flags)
5367     *flags = new_flags;
5368 }
5369
5370 static void
5371 gtk_window_constrain_position (GtkWindow    *window,
5372                                gint          new_width,
5373                                gint          new_height,
5374                                gint         *x,
5375                                gint         *y)
5376 {
5377   /* See long comments in gtk_window_move_resize()
5378    * on when it's safe to call this function.
5379    */
5380   if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
5381     {
5382       gint center_x, center_y;
5383
5384       center_window_on_monitor (window, new_width, new_height, &center_x, &center_y);
5385       
5386       *x = center_x;
5387       *y = center_y;
5388     }
5389 }
5390
5391 static void
5392 gtk_window_move_resize (GtkWindow *window)
5393 {
5394   /* Overview:
5395    *
5396    * First we determine whether any information has changed that would
5397    * cause us to revise our last configure request.  If we would send
5398    * a different configure request from last time, then
5399    * configure_request_size_changed = TRUE or
5400    * configure_request_pos_changed = TRUE. configure_request_size_changed
5401    * may be true due to new hints, a gtk_window_resize(), or whatever.
5402    * configure_request_pos_changed may be true due to gtk_window_set_position()
5403    * or gtk_window_move().
5404    *
5405    * If the configure request has changed, we send off a new one.  To
5406    * ensure GTK+ invariants are maintained (resize queue does what it
5407    * should), we go ahead and size_allocate the requested size in this
5408    * function.
5409    *
5410    * If the configure request has not changed, we don't ever resend
5411    * it, because it could mean fighting the user or window manager.
5412    *
5413    * 
5414    *   To prepare the configure request, we come up with a base size/pos:
5415    *      - the one from gtk_window_move()/gtk_window_resize()
5416    *      - else default_width, default_height if we haven't ever
5417    *        been mapped
5418    *      - else the size request if we haven't ever been mapped,
5419    *        as a substitute default size
5420    *      - else the current size of the window, as received from
5421    *        configure notifies (i.e. the current allocation)
5422    *
5423    *   If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
5424    *   the position request to be centered.
5425    */
5426   GtkWidget *widget;
5427   GtkContainer *container;
5428   GtkWindowGeometryInfo *info;
5429   GdkGeometry new_geometry;
5430   guint new_flags;
5431   GdkRectangle new_request;
5432   gboolean configure_request_size_changed;
5433   gboolean configure_request_pos_changed;
5434   gboolean hints_changed; /* do we need to send these again */
5435   GtkWindowLastGeometryInfo saved_last_info;
5436   
5437   widget = GTK_WIDGET (window);
5438   container = GTK_CONTAINER (widget);
5439   info = gtk_window_get_geometry_info (window, TRUE);
5440   
5441   configure_request_size_changed = FALSE;
5442   configure_request_pos_changed = FALSE;
5443   
5444   gtk_window_compute_configure_request (window, &new_request,
5445                                         &new_geometry, &new_flags);  
5446   
5447   /* This check implies the invariant that we never set info->last
5448    * without setting the hints and sending off a configure request.
5449    *
5450    * If we change info->last without sending the request, we may
5451    * miss a request.
5452    */
5453   if (info->last.configure_request.x != new_request.x ||
5454       info->last.configure_request.y != new_request.y)
5455     configure_request_pos_changed = TRUE;
5456
5457   if ((info->last.configure_request.width != new_request.width ||
5458        info->last.configure_request.height != new_request.height))
5459     configure_request_size_changed = TRUE;
5460   
5461   hints_changed = FALSE;
5462   
5463   if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
5464                                  &new_geometry, new_flags))
5465     {
5466       hints_changed = TRUE;
5467     }
5468   
5469   /* Position Constraints
5470    * ====================
5471    * 
5472    * POS_CENTER_ALWAYS is conceptually a constraint rather than
5473    * a default. The other POS_ values are used only when the
5474    * window is shown, not after that.
5475    * 
5476    * However, we can't implement a position constraint as
5477    * "anytime the window size changes, center the window"
5478    * because this may well end up fighting the WM or user.  In
5479    * fact it gets in an infinite loop with at least one WM.
5480    *
5481    * Basically, applications are in no way in a position to
5482    * constrain the position of a window, with one exception:
5483    * override redirect windows. (Really the intended purpose
5484    * of CENTER_ALWAYS anyhow, I would think.)
5485    *
5486    * So the way we implement this "constraint" is to say that when WE
5487    * cause a move or resize, i.e. we make a configure request changing
5488    * window size, we recompute the CENTER_ALWAYS position to reflect
5489    * the new window size, and include it in our request.  Also, if we
5490    * just turned on CENTER_ALWAYS we snap to center with a new
5491    * request.  Otherwise, if we are just NOTIFIED of a move or resize
5492    * done by someone else e.g. the window manager, we do NOT send a
5493    * new configure request.
5494    *
5495    * For override redirect windows, this works fine; all window
5496    * sizes are from our configure requests. For managed windows,
5497    * it is at least semi-sane, though who knows what the
5498    * app author is thinking.
5499    */
5500
5501   /* This condition should be kept in sync with the condition later on
5502    * that determines whether we send a configure request.  i.e. we
5503    * should do this position constraining anytime we were going to
5504    * send a configure request anyhow, plus when constraints have
5505    * changed.
5506    */
5507   if (configure_request_pos_changed ||
5508       configure_request_size_changed ||
5509       hints_changed ||
5510       info->position_constraints_changed)
5511     {
5512       /* We request the constrained position if:
5513        *  - we were changing position, and need to clamp
5514        *    the change to the constraint
5515        *  - we're changing the size anyway
5516        *  - set_position() was called to toggle CENTER_ALWAYS on
5517        */
5518
5519       gtk_window_constrain_position (window,
5520                                      new_request.width,
5521                                      new_request.height,
5522                                      &new_request.x,
5523                                      &new_request.y);
5524       
5525       /* Update whether we need to request a move */
5526       if (info->last.configure_request.x != new_request.x ||
5527           info->last.configure_request.y != new_request.y)
5528         configure_request_pos_changed = TRUE;
5529       else
5530         configure_request_pos_changed = FALSE;
5531     }
5532
5533 #if 0
5534   if (window->type == GTK_WINDOW_TOPLEVEL)
5535     {
5536       int notify_x, notify_y;
5537
5538       /* this is the position from the last configure notify */
5539       gdk_window_get_position (widget->window, &notify_x, &notify_y);
5540     
5541       g_message ("--- %s ---\n"
5542                  "last  : %d,%d\t%d x %d\n"
5543                  "this  : %d,%d\t%d x %d\n"
5544                  "alloc : %d,%d\t%d x %d\n"
5545                  "req   :      \t%d x %d\n"
5546                  "resize:      \t%d x %d\n" 
5547                  "size_changed: %d pos_changed: %d hints_changed: %d\n"
5548                  "configure_notify_received: %d\n"
5549                  "configure_request_count: %d\n"
5550                  "position_constraints_changed: %d\n",
5551                  window->title ? window->title : "(no title)",
5552                  info->last.configure_request.x,
5553                  info->last.configure_request.y,
5554                  info->last.configure_request.width,
5555                  info->last.configure_request.height,
5556                  new_request.x,
5557                  new_request.y,
5558                  new_request.width,
5559                  new_request.height,
5560                  notify_x, notify_y,
5561                  widget->allocation.width,
5562                  widget->allocation.height,
5563                  widget->requisition.width,
5564                  widget->requisition.height,
5565                  info->resize_width,
5566                  info->resize_height,
5567                  configure_request_pos_changed,
5568                  configure_request_size_changed,
5569                  hints_changed,
5570                  window->configure_notify_received,
5571                  window->configure_request_count,
5572                  info->position_constraints_changed);
5573     }
5574 #endif
5575   
5576   saved_last_info = info->last;
5577   info->last.geometry = new_geometry;
5578   info->last.flags = new_flags;
5579   info->last.configure_request = new_request;
5580   
5581   /* need to set PPosition so the WM will look at our position,
5582    * but we don't want to count PPosition coming and going as a hints
5583    * change for future iterations. So we saved info->last prior to
5584    * this.
5585    */
5586   
5587   /* Also, if the initial position was explicitly set, then we always
5588    * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
5589    * work.
5590    */
5591
5592   /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
5593    * this is an initial map
5594    */
5595   
5596   if ((configure_request_pos_changed ||
5597        info->initial_pos_set ||
5598        (window->need_default_position &&
5599         get_effective_position (window) != GTK_WIN_POS_NONE)) &&
5600       (new_flags & GDK_HINT_POS) == 0)
5601     {
5602       new_flags |= GDK_HINT_POS;
5603       hints_changed = TRUE;
5604     }
5605   
5606   /* Set hints if necessary
5607    */
5608   if (hints_changed)
5609     gdk_window_set_geometry_hints (widget->window,
5610                                    &new_geometry,
5611                                    new_flags);
5612   
5613   /* handle resizing/moving and widget tree allocation
5614    */
5615   if (window->configure_notify_received)
5616     { 
5617       GtkAllocation allocation;
5618
5619       /* If we have received a configure event since
5620        * the last time in this function, we need to
5621        * accept our new size and size_allocate child widgets.
5622        * (see gtk_window_configure_event() for more details).
5623        *
5624        * 1 or more configure notifies may have been received.
5625        * Also, configure_notify_received will only be TRUE
5626        * if all expected configure notifies have been received
5627        * (one per configure request), as an optimization.
5628        *
5629        */
5630       window->configure_notify_received = FALSE;
5631
5632       /* gtk_window_configure_event() filled in widget->allocation */
5633       allocation = widget->allocation;
5634       gtk_widget_size_allocate (widget, &allocation);
5635
5636       gdk_window_process_all_updates ();
5637       
5638       gdk_window_configure_finished (widget->window);
5639
5640       /* If the configure request changed, it means that
5641        * we either:
5642        *   1) coincidentally changed hints or widget properties
5643        *      impacting the configure request before getting
5644        *      a configure notify, or
5645        *   2) some broken widget is changing its size request
5646        *      during size allocation, resulting in
5647        *      a false appearance of changed configure request.
5648        *
5649        * For 1), we could just go ahead and ask for the
5650        * new size right now, but doing that for 2)
5651        * might well be fighting the user (and can even
5652        * trigger a loop). Since we really don't want to
5653        * do that, we requeue a resize in hopes that
5654        * by the time it gets handled, the child has seen
5655        * the light and is willing to go along with the
5656        * new size. (this happens for the zvt widget, since
5657        * the size_allocate() above will have stored the
5658        * requisition corresponding to the new size in the
5659        * zvt widget)
5660        *
5661        * This doesn't buy us anything for 1), but it shouldn't
5662        * hurt us too badly, since it is what would have
5663        * happened if we had gotten the configure event before
5664        * the new size had been set.
5665        */
5666
5667       if (configure_request_size_changed ||
5668           configure_request_pos_changed)
5669         {
5670           /* Don't change the recorded last info after all, because we
5671            * haven't actually updated to the new info yet - we decided
5672            * to postpone our configure request until later.
5673            */
5674           info->last = saved_last_info;
5675           
5676           gtk_widget_queue_resize (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
5677         }
5678
5679       return;                   /* Bail out, we didn't really process the move/resize */
5680     }
5681   else if ((configure_request_size_changed || hints_changed) &&
5682            (widget->allocation.width != new_request.width ||
5683             widget->allocation.height != new_request.height))
5684
5685     {
5686       /* We are in one of the following situations:
5687        * A. configure_request_size_changed
5688        *    our requisition has changed and we need a different window size,
5689        *    so we request it from the window manager.
5690        * B. !configure_request_size_changed && hints_changed
5691        *    the window manager rejects our size, but we have just changed the
5692        *    window manager hints, so there's a chance our request will
5693        *    be honoured this time, so we try again.
5694        *
5695        * However, if the new requisition is the same as the current allocation,
5696        * we don't request it again, since we won't get a ConfigureNotify back from
5697        * the window manager unless it decides to change our requisition. If
5698        * we don't get the ConfigureNotify back, the resize queue will never be run.
5699        */
5700
5701       /* Now send the configure request */
5702       if (configure_request_pos_changed)
5703         {
5704           if (window->frame)
5705             {
5706               gdk_window_move_resize (window->frame,
5707                                       new_request.x - window->frame_left,
5708                                       new_request.y - window->frame_top,
5709                                       new_request.width + window->frame_left + window->frame_right,
5710                                       new_request.height + window->frame_top + window->frame_bottom);
5711               gdk_window_resize (widget->window,
5712                                  new_request.width, new_request.height);
5713             }
5714           else
5715             gdk_window_move_resize (widget->window,
5716                                     new_request.x, new_request.y,
5717                                     new_request.width, new_request.height);
5718         }
5719       else  /* only size changed */
5720         {
5721           if (window->frame)
5722             gdk_window_resize (window->frame,
5723                                new_request.width + window->frame_left + window->frame_right,
5724                                new_request.height + window->frame_top + window->frame_bottom);
5725           gdk_window_resize (widget->window,
5726                              new_request.width, new_request.height);
5727         }
5728       
5729       /* Increment the number of have-not-yet-received-notify requests */
5730       window->configure_request_count += 1;
5731
5732       /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
5733        * configure event in response to our resizing request.
5734        * the configure event will cause a new resize with
5735        * ->configure_notify_received=TRUE.
5736        * until then, we want to
5737        * - discard expose events
5738        * - coalesce resizes for our children
5739        * - defer any window resizes until the configure event arrived
5740        * to achieve this, we queue a resize for the window, but remove its
5741        * resizing handler, so resizing will not be handled from the next
5742        * idle handler but when the configure event arrives.
5743        *
5744        * FIXME: we should also dequeue the pending redraws here, since
5745        * we handle those ourselves upon ->configure_notify_received==TRUE.
5746        */
5747       if (container->resize_mode == GTK_RESIZE_QUEUE)
5748         {
5749           gtk_widget_queue_resize (widget);
5750           _gtk_container_dequeue_resize_handler (container);
5751         }
5752     }
5753   else
5754     {
5755       /* Handle any position changes.
5756        */
5757       if (configure_request_pos_changed)
5758         {
5759           if (window->frame)
5760             {
5761               gdk_window_move (window->frame,
5762                                new_request.x - window->frame_left,
5763                                new_request.y - window->frame_top);
5764             }
5765           else
5766             gdk_window_move (widget->window,
5767                              new_request.x, new_request.y);
5768         }
5769
5770       /* And run the resize queue.
5771        */
5772       gtk_container_resize_children (container);
5773     }
5774   
5775   /* We have now processed a move/resize since the last position
5776    * constraint change, setting of the initial position, or resize.
5777    * (Not resetting these flags here can lead to infinite loops for
5778    * GTK_RESIZE_IMMEDIATE containers)
5779    */
5780   info->position_constraints_changed = FALSE;
5781   info->initial_pos_set = FALSE;
5782   info->resize_width = -1;
5783   info->resize_height = -1;
5784 }
5785
5786 /* Compare two sets of Geometry hints for equality.
5787  */
5788 static gboolean
5789 gtk_window_compare_hints (GdkGeometry *geometry_a,
5790                           guint        flags_a,
5791                           GdkGeometry *geometry_b,
5792                           guint        flags_b)
5793 {
5794   if (flags_a != flags_b)
5795     return FALSE;
5796   
5797   if ((flags_a & GDK_HINT_MIN_SIZE) &&
5798       (geometry_a->min_width != geometry_b->min_width ||
5799        geometry_a->min_height != geometry_b->min_height))
5800     return FALSE;
5801
5802   if ((flags_a & GDK_HINT_MAX_SIZE) &&
5803       (geometry_a->max_width != geometry_b->max_width ||
5804        geometry_a->max_height != geometry_b->max_height))
5805     return FALSE;
5806
5807   if ((flags_a & GDK_HINT_BASE_SIZE) &&
5808       (geometry_a->base_width != geometry_b->base_width ||
5809        geometry_a->base_height != geometry_b->base_height))
5810     return FALSE;
5811
5812   if ((flags_a & GDK_HINT_ASPECT) &&
5813       (geometry_a->min_aspect != geometry_b->min_aspect ||
5814        geometry_a->max_aspect != geometry_b->max_aspect))
5815     return FALSE;
5816
5817   if ((flags_a & GDK_HINT_RESIZE_INC) &&
5818       (geometry_a->width_inc != geometry_b->width_inc ||
5819        geometry_a->height_inc != geometry_b->height_inc))
5820     return FALSE;
5821
5822   if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
5823       geometry_a->win_gravity != geometry_b->win_gravity)
5824     return FALSE;
5825
5826   return TRUE;
5827 }
5828
5829 void
5830 _gtk_window_constrain_size (GtkWindow   *window,
5831                             gint         width,
5832                             gint         height,
5833                             gint        *new_width,
5834                             gint        *new_height)
5835 {
5836   GtkWindowGeometryInfo *info;
5837
5838   g_return_if_fail (GTK_IS_WINDOW (window));
5839
5840   info = window->geometry_info;
5841   if (info)
5842     {
5843       GdkWindowHints flags = info->last.flags;
5844       GdkGeometry *geometry = &info->last.geometry;
5845       
5846       gtk_window_constrain_size (window,
5847                                  geometry,
5848                                  flags,
5849                                  width,
5850                                  height,
5851                                  new_width,
5852                                  new_height);
5853     }
5854 }
5855
5856 static void 
5857 gtk_window_constrain_size (GtkWindow   *window,
5858                            GdkGeometry *geometry,
5859                            guint        flags,
5860                            gint         width,
5861                            gint         height,
5862                            gint        *new_width,
5863                            gint        *new_height)
5864 {
5865   gdk_window_constrain_size (geometry, flags, width, height,
5866                              new_width, new_height);
5867 }
5868
5869 /* Compute the set of geometry hints and flags for a window
5870  * based on the application set geometry, and requisiition
5871  * of the window. gtk_widget_size_request() must have been
5872  * called first.
5873  */
5874 static void
5875 gtk_window_compute_hints (GtkWindow   *window,
5876                           GdkGeometry *new_geometry,
5877                           guint       *new_flags)
5878 {
5879   GtkWidget *widget;
5880   gint extra_width = 0;
5881   gint extra_height = 0;
5882   GtkWindowGeometryInfo *geometry_info;
5883   GtkRequisition requisition;
5884
5885   widget = GTK_WIDGET (window);
5886   
5887   gtk_widget_get_child_requisition (widget, &requisition);
5888   geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
5889
5890   if (geometry_info)
5891     {
5892       *new_flags = geometry_info->mask;
5893       *new_geometry = geometry_info->geometry;
5894     }
5895   else
5896     {
5897       *new_flags = 0;
5898     }
5899   
5900   if (geometry_info && geometry_info->widget)
5901     {
5902       GtkRequisition child_requisition;
5903
5904       /* FIXME: This really isn't right. It gets the min size wrong and forces
5905        * callers to do horrible hacks like set a huge usize on the child requisition
5906        * to get the base size right. We really want to find the answers to:
5907        *
5908        *  - If the geometry widget was infinitely big, how much extra space
5909        *    would be needed for the stuff around it.
5910        *
5911        *  - If the geometry widget was infinitely small, how big would the
5912        *    window still have to be.
5913        *
5914        * Finding these answers would be a bit of a mess here. (Bug #68668)
5915        */
5916       gtk_widget_get_child_requisition (geometry_info->widget, &child_requisition);
5917       
5918       extra_width = widget->requisition.width - child_requisition.width;
5919       extra_height = widget->requisition.height - child_requisition.height;
5920     }
5921
5922   /* We don't want to set GDK_HINT_POS in here, we just set it
5923    * in gtk_window_move_resize() when we want the position
5924    * honored.
5925    */
5926   
5927   if (*new_flags & GDK_HINT_BASE_SIZE)
5928     {
5929       new_geometry->base_width += extra_width;
5930       new_geometry->base_height += extra_height;
5931     }
5932   else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
5933            (*new_flags & GDK_HINT_RESIZE_INC) &&
5934            ((extra_width != 0) || (extra_height != 0)))
5935     {
5936       *new_flags |= GDK_HINT_BASE_SIZE;
5937       
5938       new_geometry->base_width = extra_width;
5939       new_geometry->base_height = extra_height;
5940     }
5941   
5942   if (*new_flags & GDK_HINT_MIN_SIZE)
5943     {
5944       if (new_geometry->min_width < 0)
5945         new_geometry->min_width = requisition.width;
5946       else
5947         new_geometry->min_width += extra_width;
5948
5949       if (new_geometry->min_height < 0)
5950         new_geometry->min_height = requisition.height;
5951       else
5952         new_geometry->min_height += extra_height;
5953     }
5954   else if (!window->allow_shrink)
5955     {
5956       *new_flags |= GDK_HINT_MIN_SIZE;
5957       
5958       new_geometry->min_width = requisition.width;
5959       new_geometry->min_height = requisition.height;
5960     }
5961   
5962   if (*new_flags & GDK_HINT_MAX_SIZE)
5963     {
5964       if (new_geometry->max_width < 0)
5965         new_geometry->max_width = requisition.width;
5966       else
5967         new_geometry->max_width += extra_width;
5968
5969       if (new_geometry->max_height < 0)
5970         new_geometry->max_height = requisition.height;
5971       else
5972         new_geometry->max_height += extra_height;
5973     }
5974   else if (!window->allow_grow)
5975     {
5976       *new_flags |= GDK_HINT_MAX_SIZE;
5977       
5978       new_geometry->max_width = requisition.width;
5979       new_geometry->max_height = requisition.height;
5980     }
5981
5982   *new_flags |= GDK_HINT_WIN_GRAVITY;
5983   new_geometry->win_gravity = window->gravity;
5984 }
5985
5986 /***********************
5987  * Redrawing functions *
5988  ***********************/
5989
5990 static void
5991 gtk_window_paint (GtkWidget     *widget,
5992                   GdkRectangle *area)
5993 {
5994   gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL, 
5995                       GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
5996 }
5997
5998 static gint
5999 gtk_window_expose (GtkWidget      *widget,
6000                    GdkEventExpose *event)
6001 {
6002   if (!GTK_WIDGET_APP_PAINTABLE (widget))
6003     gtk_window_paint (widget, &event->area);
6004   
6005   if (GTK_WIDGET_CLASS (parent_class)->expose_event)
6006     return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
6007
6008   return FALSE;
6009 }
6010
6011 /**
6012  * gtk_window_set_has_frame:
6013  * @window: a #GtkWindow
6014  * @setting: a boolean
6015  *
6016  * (Note: this is a special-purpose function for the framebuffer port,
6017  *  that causes GTK+ to draw its own window border. For most applications,
6018  *  you want gtk_window_set_decorated() instead, which tells the window
6019  *  manager whether to draw the window border.)
6020  * 
6021  * If this function is called on a window with setting of %TRUE, before
6022  * it is realized or showed, it will have a "frame" window around
6023  * @window->window, accessible in @window->frame. Using the signal 
6024  * frame_event you can receive all events targeted at the frame.
6025  * 
6026  * This function is used by the linux-fb port to implement managed
6027  * windows, but it could concievably be used by X-programs that
6028  * want to do their own window decorations.
6029  *
6030  **/
6031 void
6032 gtk_window_set_has_frame (GtkWindow *window, 
6033                           gboolean   setting)
6034 {
6035   g_return_if_fail (GTK_IS_WINDOW (window));
6036   g_return_if_fail (!GTK_WIDGET_REALIZED (window));
6037
6038   window->has_frame = setting != FALSE;
6039 }
6040
6041 /**
6042  * gtk_window_get_has_frame:
6043  * @window: a #GtkWindow
6044  * 
6045  * Accessor for whether the window has a frame window exterior to
6046  * @window->window. Gets the value set by gtk_window_set_has_frame ().
6047  *
6048  * Return value: %TRUE if a frame has been added to the window
6049  *   via gtk_window_set_has_frame().
6050  **/
6051 gboolean
6052 gtk_window_get_has_frame (GtkWindow *window)
6053 {
6054   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6055
6056   return window->has_frame;
6057 }
6058
6059 /**
6060  * gtk_window_set_frame_dimensions:
6061  * @window: a #GtkWindow that has a frame
6062  * @left: The width of the left border
6063  * @top: The height of the top border
6064  * @right: The width of the right border
6065  * @bottom: The height of the bottom border
6066  *
6067  * (Note: this is a special-purpose function intended for the framebuffer
6068  *  port; see gtk_window_set_has_frame(). It will have no effect on the
6069  *  window border drawn by the window manager, which is the normal
6070  *  case when using the X Window system.)
6071  *
6072  * For windows with frames (see gtk_window_set_has_frame()) this function
6073  * can be used to change the size of the frame border.
6074  **/
6075 void
6076 gtk_window_set_frame_dimensions (GtkWindow *window, 
6077                                  gint       left,
6078                                  gint       top,
6079                                  gint       right,
6080                                  gint       bottom)
6081 {
6082   GtkWidget *widget;
6083
6084   g_return_if_fail (GTK_IS_WINDOW (window));
6085
6086   widget = GTK_WIDGET (window);
6087
6088   if (window->frame_left == left &&
6089       window->frame_top == top &&
6090       window->frame_right == right && 
6091       window->frame_bottom == bottom)
6092     return;
6093
6094   window->frame_left = left;
6095   window->frame_top = top;
6096   window->frame_right = right;
6097   window->frame_bottom = bottom;
6098
6099   if (GTK_WIDGET_REALIZED (widget) && window->frame)
6100     {
6101       gint width = widget->allocation.width + left + right;
6102       gint height = widget->allocation.height + top + bottom;
6103       gdk_window_resize (window->frame, width, height);
6104       gtk_decorated_window_move_resize_window (window,
6105                                                left, top,
6106                                                widget->allocation.width,
6107                                                widget->allocation.height);
6108     }
6109 }
6110
6111 /**
6112  * gtk_window_present:
6113  * @window: a #GtkWindow
6114  *
6115  * Presents a window to the user. This may mean raising the window
6116  * in the stacking order, deiconifying it, moving it to the current
6117  * desktop, and/or giving it the keyboard focus, possibly dependent
6118  * on the user's platform, window manager, and preferences.
6119  *
6120  * If @window is hidden, this function calls gtk_widget_show()
6121  * as well.
6122  * 
6123  * This function should be used when the user tries to open a window
6124  * that's already open. Say for example the preferences dialog is
6125  * currently open, and the user chooses Preferences from the menu
6126  * a second time; use gtk_window_present() to move the already-open dialog
6127  * where the user can see it.
6128  *
6129  * If you are calling this function in response to a user interaction,
6130  * it is preferable to use gdk_window_present_with_time().
6131  * 
6132  **/
6133 void
6134 gtk_window_present (GtkWindow *window)
6135 {
6136   gtk_window_present_with_time (window, GDK_CURRENT_TIME);
6137 }
6138
6139 /**
6140  * gtk_window_present_with_time:
6141  * @window: a #GtkWindow
6142  * @timestamp: the timestamp of the user interaction (typically a 
6143  *   button or key press event) which triggered this call
6144  *
6145  * Presents a window to the user in response to a user interaction.
6146  * If you need to present a window without a timestamp, use 
6147  * gtk_window_present(). See gtk_window_present() for details. 
6148  * 
6149  * Since: 2.8
6150  **/
6151 void
6152 gtk_window_present_with_time (GtkWindow *window,
6153                               guint32    timestamp)
6154 {
6155   GtkWidget *widget;
6156
6157   g_return_if_fail (GTK_IS_WINDOW (window));
6158
6159   widget = GTK_WIDGET (window);
6160
6161   if (GTK_WIDGET_VISIBLE (window))
6162     {
6163       g_assert (widget->window != NULL);
6164       
6165       gdk_window_show (widget->window);
6166
6167       /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
6168       if (timestamp == GDK_CURRENT_TIME)
6169         {
6170 #ifdef GDK_WINDOWING_X11
6171           GdkDisplay *display;
6172
6173           display = gtk_widget_get_display (GTK_WIDGET (window));
6174           timestamp = gdk_x11_display_get_user_time (display);
6175 #else
6176           timestamp = gtk_get_current_event_time ();
6177 #endif
6178         }
6179
6180       gdk_window_focus (widget->window, timestamp);
6181     }
6182   else
6183     {
6184       gtk_widget_show (widget);
6185     }
6186 }
6187
6188 /**
6189  * gtk_window_iconify:
6190  * @window: a #GtkWindow
6191  *
6192  * Asks to iconify (i.e. minimize) the specified @window. Note that
6193  * you shouldn't assume the window is definitely iconified afterward,
6194  * because other entities (e.g. the user or <link
6195  * linkend="gtk-X11-arch">window manager</link>) could deiconify it
6196  * again, or there may not be a window manager in which case
6197  * iconification isn't possible, etc. But normally the window will end
6198  * up iconified. Just don't write code that crashes if not.
6199  *
6200  * It's permitted to call this function before showing a window,
6201  * in which case the window will be iconified before it ever appears
6202  * onscreen.
6203  *
6204  * You can track iconification via the "window_state_event" signal
6205  * on #GtkWidget.
6206  * 
6207  **/
6208 void
6209 gtk_window_iconify (GtkWindow *window)
6210 {
6211   GtkWidget *widget;
6212   GdkWindow *toplevel;
6213   
6214   g_return_if_fail (GTK_IS_WINDOW (window));
6215
6216   widget = GTK_WIDGET (window);
6217
6218   window->iconify_initially = TRUE;
6219
6220   if (window->frame)
6221     toplevel = window->frame;
6222   else
6223     toplevel = widget->window;
6224   
6225   if (toplevel != NULL)
6226     gdk_window_iconify (toplevel);
6227 }
6228
6229 /**
6230  * gtk_window_deiconify:
6231  * @window: a #GtkWindow
6232  *
6233  * Asks to deiconify (i.e. unminimize) the specified @window. Note
6234  * that you shouldn't assume the window is definitely deiconified
6235  * afterward, because other entities (e.g. the user or <link
6236  * linkend="gtk-X11-arch">window manager</link>) could iconify it
6237  * again before your code which assumes deiconification gets to run.
6238  *
6239  * You can track iconification via the "window_state_event" signal
6240  * on #GtkWidget.
6241  **/
6242 void
6243 gtk_window_deiconify (GtkWindow *window)
6244 {
6245   GtkWidget *widget;
6246   GdkWindow *toplevel;
6247   
6248   g_return_if_fail (GTK_IS_WINDOW (window));
6249
6250   widget = GTK_WIDGET (window);
6251
6252   window->iconify_initially = FALSE;
6253
6254   if (window->frame)
6255     toplevel = window->frame;
6256   else
6257     toplevel = widget->window;
6258   
6259   if (toplevel != NULL)
6260     gdk_window_deiconify (toplevel);
6261 }
6262
6263 /**
6264  * gtk_window_stick:
6265  * @window: a #GtkWindow
6266  *
6267  * Asks to stick @window, which means that it will appear on all user
6268  * desktops. Note that you shouldn't assume the window is definitely
6269  * stuck afterward, because other entities (e.g. the user or <link
6270  * linkend="gtk-X11-arch">window manager</link>) could unstick it
6271  * again, and some window managers do not support sticking
6272  * windows. But normally the window will end up stuck. Just don't
6273  * write code that crashes if not.
6274  *
6275  * It's permitted to call this function before showing a window.
6276  *
6277  * You can track stickiness via the "window_state_event" signal
6278  * on #GtkWidget.
6279  * 
6280  **/
6281 void
6282 gtk_window_stick (GtkWindow *window)
6283 {
6284   GtkWidget *widget;
6285   GdkWindow *toplevel;
6286   
6287   g_return_if_fail (GTK_IS_WINDOW (window));
6288
6289   widget = GTK_WIDGET (window);
6290
6291   window->stick_initially = TRUE;
6292
6293   if (window->frame)
6294     toplevel = window->frame;
6295   else
6296     toplevel = widget->window;
6297   
6298   if (toplevel != NULL)
6299     gdk_window_stick (toplevel);
6300 }
6301
6302 /**
6303  * gtk_window_unstick:
6304  * @window: a #GtkWindow
6305  *
6306  * Asks to unstick @window, which means that it will appear on only
6307  * one of the user's desktops. Note that you shouldn't assume the
6308  * window is definitely unstuck afterward, because other entities
6309  * (e.g. the user or <link linkend="gtk-X11-arch">window
6310  * manager</link>) could stick it again. But normally the window will
6311  * end up stuck. Just don't write code that crashes if not.
6312  *
6313  * You can track stickiness via the "window_state_event" signal
6314  * on #GtkWidget.
6315  * 
6316  **/
6317 void
6318 gtk_window_unstick (GtkWindow *window)
6319 {
6320   GtkWidget *widget;
6321   GdkWindow *toplevel;
6322   
6323   g_return_if_fail (GTK_IS_WINDOW (window));
6324
6325   widget = GTK_WIDGET (window);
6326
6327   window->stick_initially = FALSE;
6328
6329   if (window->frame)
6330     toplevel = window->frame;
6331   else
6332     toplevel = widget->window;
6333   
6334   if (toplevel != NULL)
6335     gdk_window_unstick (toplevel);
6336 }
6337
6338 /**
6339  * gtk_window_maximize:
6340  * @window: a #GtkWindow
6341  *
6342  * Asks to maximize @window, so that it becomes full-screen. Note that
6343  * you shouldn't assume the window is definitely maximized afterward,
6344  * because other entities (e.g. the user or <link
6345  * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
6346  * again, and not all window managers support maximization. But
6347  * normally the window will end up maximized. Just don't write code
6348  * that crashes if not.
6349  *
6350  * It's permitted to call this function before showing a window,
6351  * in which case the window will be maximized when it appears onscreen
6352  * initially.
6353  *
6354  * You can track maximization via the "window_state_event" signal
6355  * on #GtkWidget.
6356  * 
6357  **/
6358 void
6359 gtk_window_maximize (GtkWindow *window)
6360 {
6361   GtkWidget *widget;
6362   GdkWindow *toplevel;
6363   
6364   g_return_if_fail (GTK_IS_WINDOW (window));
6365
6366   widget = GTK_WIDGET (window);
6367
6368   window->maximize_initially = TRUE;
6369
6370   if (window->frame)
6371     toplevel = window->frame;
6372   else
6373     toplevel = widget->window;
6374   
6375   if (toplevel != NULL)
6376     gdk_window_maximize (toplevel);
6377 }
6378
6379 /**
6380  * gtk_window_unmaximize:
6381  * @window: a #GtkWindow
6382  *
6383  * Asks to unmaximize @window. Note that you shouldn't assume the
6384  * window is definitely unmaximized afterward, because other entities
6385  * (e.g. the user or <link linkend="gtk-X11-arch">window
6386  * manager</link>) could maximize it again, and not all window
6387  * managers honor requests to unmaximize. But normally the window will
6388  * end up unmaximized. Just don't write code that crashes if not.
6389  *
6390  * You can track maximization via the "window_state_event" signal
6391  * on #GtkWidget.
6392  * 
6393  **/
6394 void
6395 gtk_window_unmaximize (GtkWindow *window)
6396 {
6397   GtkWidget *widget;
6398   GdkWindow *toplevel;
6399   
6400   g_return_if_fail (GTK_IS_WINDOW (window));
6401
6402   widget = GTK_WIDGET (window);
6403
6404   window->maximize_initially = FALSE;
6405
6406   if (window->frame)
6407     toplevel = window->frame;
6408   else
6409     toplevel = widget->window;
6410   
6411   if (toplevel != NULL)
6412     gdk_window_unmaximize (toplevel);
6413 }
6414
6415 /**
6416  * gtk_window_fullscreen:
6417  * @window: a #GtkWindow
6418  *
6419  * Asks to place @window in the fullscreen state. Note that you
6420  * shouldn't assume the window is definitely full screen afterward,
6421  * because other entities (e.g. the user or <link
6422  * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
6423  * again, and not all window managers honor requests to fullscreen
6424  * windows. But normally the window will end up fullscreen. Just
6425  * don't write code that crashes if not.
6426  *
6427  * You can track the fullscreen state via the "window_state_event" signal
6428  * on #GtkWidget.
6429  * 
6430  * Since: 2.2
6431  **/
6432 void
6433 gtk_window_fullscreen (GtkWindow *window)
6434 {
6435   GtkWidget *widget;
6436   GdkWindow *toplevel;
6437   GtkWindowPrivate *priv;
6438   
6439   g_return_if_fail (GTK_IS_WINDOW (window));
6440
6441   widget = GTK_WIDGET (window);
6442   priv = GTK_WINDOW_GET_PRIVATE (window);
6443   
6444   priv->fullscreen_initially = TRUE;
6445
6446   if (window->frame)
6447     toplevel = window->frame;
6448   else
6449     toplevel = widget->window;
6450   
6451   if (toplevel != NULL)
6452     gdk_window_fullscreen (toplevel);
6453 }
6454
6455 /**
6456  * gtk_window_unfullscreen:
6457  * @window: a #GtkWindow
6458  *
6459  * Asks to toggle off the fullscreen state for @window. Note that you
6460  * shouldn't assume the window is definitely not full screen
6461  * afterward, because other entities (e.g. the user or <link
6462  * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
6463  * again, and not all window managers honor requests to unfullscreen
6464  * windows. But normally the window will end up restored to its normal
6465  * state. Just don't write code that crashes if not.
6466  *
6467  * You can track the fullscreen state via the "window_state_event" signal
6468  * on #GtkWidget.
6469  * 
6470  * Since: 2.2
6471  **/
6472 void
6473 gtk_window_unfullscreen (GtkWindow *window)
6474 {
6475   GtkWidget *widget;
6476   GdkWindow *toplevel;
6477   GtkWindowPrivate *priv;
6478   
6479   g_return_if_fail (GTK_IS_WINDOW (window));
6480
6481   widget = GTK_WIDGET (window);
6482   priv = GTK_WINDOW_GET_PRIVATE (window);
6483   
6484   priv->fullscreen_initially = FALSE;
6485
6486   if (window->frame)
6487     toplevel = window->frame;
6488   else
6489     toplevel = widget->window;
6490   
6491   if (toplevel != NULL)
6492     gdk_window_unfullscreen (toplevel);
6493 }
6494
6495 /**
6496  * gtk_window_set_keep_above:
6497  * @window: a #GtkWindow
6498  * @setting: whether to keep @window above other windows
6499  *
6500  * Asks to keep @window above, so that it stays on top. Note that
6501  * you shouldn't assume the window is definitely above afterward,
6502  * because other entities (e.g. the user or <link
6503  * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
6504  * and not all window managers support keeping windows above. But
6505  * normally the window will end kept above. Just don't write code
6506  * that crashes if not.
6507  *
6508  * It's permitted to call this function before showing a window,
6509  * in which case the window will be kept above when it appears onscreen
6510  * initially.
6511  *
6512  * You can track the above state via the "window_state_event" signal
6513  * on #GtkWidget.
6514  *
6515  * Note that, according to the <ulink 
6516  * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window 
6517  * Manager Hints</ulink> specification, the above state is mainly meant 
6518  * for user preferences and should not be used by applications e.g. for 
6519  * drawing attention to their dialogs.
6520  *
6521  * Since: 2.4
6522  **/
6523 void
6524 gtk_window_set_keep_above (GtkWindow *window,
6525                            gboolean   setting)
6526 {
6527   GtkWidget *widget;
6528   GtkWindowPrivate *priv;
6529   GdkWindow *toplevel;
6530
6531   g_return_if_fail (GTK_IS_WINDOW (window));
6532
6533   widget = GTK_WIDGET (window);
6534   priv = GTK_WINDOW_GET_PRIVATE (window);
6535
6536   priv->above_initially = setting;
6537   if (setting)
6538     priv->below_initially = FALSE;
6539
6540   if (window->frame)
6541     toplevel = window->frame;
6542   else
6543     toplevel = widget->window;
6544
6545   if (toplevel != NULL)
6546     gdk_window_set_keep_above (toplevel, setting);
6547 }
6548
6549 /**
6550  * gtk_window_set_keep_below:
6551  * @window: a #GtkWindow
6552  * @setting: whether to keep @window below other windows
6553  *
6554  * Asks to keep @window below, so that it stays in bottom. Note that
6555  * you shouldn't assume the window is definitely below afterward,
6556  * because other entities (e.g. the user or <link
6557  * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
6558  * and not all window managers support putting windows below. But
6559  * normally the window will be kept below. Just don't write code
6560  * that crashes if not.
6561  *
6562  * It's permitted to call this function before showing a window,
6563  * in which case the window will be kept below when it appears onscreen
6564  * initially.
6565  *
6566  * You can track the below state via the "window_state_event" signal
6567  * on #GtkWidget.
6568  *
6569  * Note that, according to the <ulink 
6570  * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window 
6571  * Manager Hints</ulink> specification, the above state is mainly meant 
6572  * for user preferences and should not be used by applications e.g. for 
6573  * drawing attention to their dialogs.
6574  *
6575  * Since: 2.4
6576  **/
6577 void
6578 gtk_window_set_keep_below (GtkWindow *window,
6579                            gboolean   setting)
6580 {
6581   GtkWidget *widget;
6582   GtkWindowPrivate *priv;
6583   GdkWindow *toplevel;
6584
6585   g_return_if_fail (GTK_IS_WINDOW (window));
6586
6587   widget = GTK_WIDGET (window);
6588   priv = GTK_WINDOW_GET_PRIVATE (window);
6589
6590   priv->below_initially = setting;
6591   if (setting)
6592     priv->above_initially = FALSE;
6593
6594   if (window->frame)
6595     toplevel = window->frame;
6596   else
6597     toplevel = widget->window;
6598
6599   if (toplevel != NULL)
6600     gdk_window_set_keep_below (toplevel, setting);
6601 }
6602
6603 /**
6604  * gtk_window_set_resizable:
6605  * @window: a #GtkWindow
6606  * @resizable: %TRUE if the user can resize this window
6607  *
6608  * Sets whether the user can resize a window. Windows are user resizable
6609  * by default.
6610  **/
6611 void
6612 gtk_window_set_resizable (GtkWindow *window,
6613                           gboolean   resizable)
6614 {
6615   g_return_if_fail (GTK_IS_WINDOW (window));
6616
6617   gtk_window_set_policy (window, FALSE, resizable, FALSE);
6618 }
6619
6620 /**
6621  * gtk_window_get_resizable:
6622  * @window: a #GtkWindow
6623  *
6624  * Gets the value set by gtk_window_set_resizable().
6625  *
6626  * Return value: %TRUE if the user can resize the window
6627  **/
6628 gboolean
6629 gtk_window_get_resizable (GtkWindow *window)
6630 {
6631   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6632
6633   /* allow_grow is most likely to indicate the semantic concept we
6634    * mean by "resizable" (and will be a reliable indicator if
6635    * set_policy() hasn't been called)
6636    */
6637   return window->allow_grow;
6638 }
6639
6640 /**
6641  * gtk_window_set_gravity:
6642  * @window: a #GtkWindow
6643  * @gravity: window gravity
6644  *
6645  * Window gravity defines the meaning of coordinates passed to
6646  * gtk_window_move(). See gtk_window_move() and #GdkGravity for
6647  * more details.
6648  *
6649  * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
6650  * typically "do what you mean."
6651  *
6652  **/
6653 void
6654 gtk_window_set_gravity (GtkWindow *window,
6655                         GdkGravity gravity)
6656 {
6657   g_return_if_fail (GTK_IS_WINDOW (window));
6658
6659   if (gravity != window->gravity)
6660     {
6661       window->gravity = gravity;
6662
6663       /* gtk_window_move_resize() will adapt gravity
6664        */
6665       gtk_widget_queue_resize (GTK_WIDGET (window));
6666
6667       g_object_notify (G_OBJECT (window), "gravity");
6668     }
6669 }
6670
6671 /**
6672  * gtk_window_get_gravity:
6673  * @window: a #GtkWindow
6674  *
6675  * Gets the value set by gtk_window_set_gravity().
6676  *
6677  * Return value: window gravity
6678  **/
6679 GdkGravity
6680 gtk_window_get_gravity (GtkWindow *window)
6681 {
6682   g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
6683
6684   return window->gravity;
6685 }
6686
6687 /**
6688  * gtk_window_begin_resize_drag:
6689  * @window: a #GtkWindow
6690  * @button: mouse button that initiated the drag
6691  * @edge: position of the resize control
6692  * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
6693  * @root_y: Y position where the user clicked to initiate the drag
6694  * @timestamp: timestamp from the click event that initiated the drag
6695  *
6696  * Starts resizing a window. This function is used if an application
6697  * has window resizing controls. When GDK can support it, the resize
6698  * will be done using the standard mechanism for the <link
6699  * linkend="gtk-X11-arch">window manager</link> or windowing
6700  * system. Otherwise, GDK will try to emulate window resizing,
6701  * potentially not all that well, depending on the windowing system.
6702  * 
6703  **/
6704 void
6705 gtk_window_begin_resize_drag  (GtkWindow    *window,
6706                                GdkWindowEdge edge,
6707                                gint          button,
6708                                gint          root_x,
6709                                gint          root_y,
6710                                guint32       timestamp)
6711 {
6712   GtkWidget *widget;
6713   GdkWindow *toplevel;
6714   
6715   g_return_if_fail (GTK_IS_WINDOW (window));
6716   g_return_if_fail (GTK_WIDGET_VISIBLE (window));
6717   
6718   widget = GTK_WIDGET (window);
6719   
6720   if (window->frame)
6721     toplevel = window->frame;
6722   else
6723     toplevel = widget->window;
6724   
6725   gdk_window_begin_resize_drag (toplevel,
6726                                 edge, button,
6727                                 root_x, root_y,
6728                                 timestamp);
6729 }
6730
6731 /**
6732  * gtk_window_get_frame_dimensions:
6733  * @window: a #GtkWindow
6734  * @left: location to store the width of the frame at the left, or %NULL
6735  * @top: location to store the height of the frame at the top, or %NULL
6736  * @right: location to store the width of the frame at the returns, or %NULL
6737  * @bottom: location to store the height of the frame at the bottom, or %NULL
6738  *
6739  * (Note: this is a special-purpose function intended for the
6740  *  framebuffer port; see gtk_window_set_has_frame(). It will not
6741  *  return the size of the window border drawn by the <link
6742  *  linkend="gtk-X11-arch">window manager</link>, which is the normal
6743  *  case when using a windowing system.  See
6744  *  gdk_window_get_frame_extents() to get the standard window border
6745  *  extents.)
6746  * 
6747  * Retrieves the dimensions of the frame window for this toplevel.
6748  * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
6749  **/
6750 void
6751 gtk_window_get_frame_dimensions (GtkWindow *window,
6752                                  gint      *left,
6753                                  gint      *top,
6754                                  gint      *right,
6755                                  gint      *bottom)
6756 {
6757   g_return_if_fail (GTK_IS_WINDOW (window));
6758
6759   if (left)
6760     *left = window->frame_left;
6761   if (top)
6762     *top = window->frame_top;
6763   if (right)
6764     *right = window->frame_right;
6765   if (bottom)
6766     *bottom = window->frame_bottom;
6767 }
6768
6769 /**
6770  * gtk_window_begin_move_drag:
6771  * @window: a #GtkWindow
6772  * @button: mouse button that initiated the drag
6773  * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
6774  * @root_y: Y position where the user clicked to initiate the drag
6775  * @timestamp: timestamp from the click event that initiated the drag
6776  *
6777  * Starts moving a window. This function is used if an application has
6778  * window movement grips. When GDK can support it, the window movement
6779  * will be done using the standard mechanism for the <link
6780  * linkend="gtk-X11-arch">window manager</link> or windowing
6781  * system. Otherwise, GDK will try to emulate window movement,
6782  * potentially not all that well, depending on the windowing system.
6783  * 
6784  **/
6785 void
6786 gtk_window_begin_move_drag  (GtkWindow *window,
6787                              gint       button,
6788                              gint       root_x,
6789                              gint       root_y,
6790                              guint32    timestamp)
6791 {
6792   GtkWidget *widget;
6793   GdkWindow *toplevel;
6794   
6795   g_return_if_fail (GTK_IS_WINDOW (window));
6796   g_return_if_fail (GTK_WIDGET_VISIBLE (window));
6797   
6798   widget = GTK_WIDGET (window);
6799   
6800   if (window->frame)
6801     toplevel = window->frame;
6802   else
6803     toplevel = widget->window;
6804   
6805   gdk_window_begin_move_drag (toplevel,
6806                               button,
6807                               root_x, root_y,
6808                               timestamp);
6809 }
6810
6811 /** 
6812  * gtk_window_set_screen:
6813  * @window: a #GtkWindow.
6814  * @screen: a #GdkScreen.
6815  *
6816  * Sets the #GdkScreen where the @window is displayed; if
6817  * the window is already mapped, it will be unmapped, and
6818  * then remapped on the new screen.
6819  *
6820  * Since: 2.2
6821  */
6822 void
6823 gtk_window_set_screen (GtkWindow *window,
6824                        GdkScreen *screen)
6825 {
6826   GtkWidget *widget;
6827   GdkScreen *previous_screen;
6828   gboolean was_mapped;
6829   
6830   g_return_if_fail (GTK_IS_WINDOW (window));
6831   g_return_if_fail (GDK_IS_SCREEN (screen));
6832
6833   if (screen == window->screen)
6834     return;
6835
6836   widget = GTK_WIDGET (window);
6837
6838   previous_screen = window->screen;
6839   was_mapped = GTK_WIDGET_MAPPED (widget);
6840
6841   if (was_mapped)
6842     gtk_widget_unmap (widget);
6843   if (GTK_WIDGET_REALIZED (widget))
6844     gtk_widget_unrealize (widget);
6845       
6846   gtk_window_free_key_hash (window);
6847   window->screen = screen;
6848   gtk_widget_reset_rc_styles (widget);
6849   if (screen != previous_screen)
6850     _gtk_widget_propagate_screen_changed (widget, previous_screen);
6851   g_object_notify (G_OBJECT (window), "screen");
6852
6853   if (was_mapped)
6854     gtk_widget_map (widget);
6855 }
6856
6857 static GdkScreen *
6858 gtk_window_check_screen (GtkWindow *window)
6859 {
6860   if (window->screen)
6861     return window->screen;
6862   else
6863     {
6864       g_warning ("Screen for GtkWindow not set; you must always set\n"
6865                  "a screen for a GtkWindow before using the window");
6866       return NULL;
6867     }
6868 }
6869
6870 /** 
6871  * gtk_window_get_screen:
6872  * @window: a #GtkWindow.
6873  *
6874  * Returns the #GdkScreen associated with @window.
6875  *
6876  * Return value: a #GdkScreen.
6877  *
6878  * Since: 2.2
6879  */
6880 GdkScreen*
6881 gtk_window_get_screen (GtkWindow *window)
6882 {
6883   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
6884    
6885   return window->screen;
6886 }
6887
6888 /**
6889  * gtk_window_is_active:
6890  * @window: a #GtkWindow
6891  * 
6892  * Returns whether the window is part of the current active toplevel.
6893  * (That is, the toplevel window receiving keystrokes.)
6894  * The return value is %TRUE if the window is active toplevel
6895  * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
6896  * You might use this function if you wanted to draw a widget
6897  * differently in an active window from a widget in an inactive window.
6898  * See gtk_window_has_toplevel_focus()
6899  * 
6900  * Return value: %TRUE if the window part of the current active window.
6901  *
6902  * Since: 2.4
6903  **/
6904 gboolean
6905 gtk_window_is_active (GtkWindow *window)
6906 {
6907   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6908
6909   return window->is_active;
6910 }
6911
6912 /**
6913  * gtk_window_has_toplevel_focus:
6914  * @window: a #GtkWindow
6915  * 
6916  * Returns whether the input focus is within this GtkWindow.
6917  * For real toplevel windows, this is identical to gtk_window_is_active(),
6918  * but for embedded windows, like #GtkPlug, the results will differ.
6919  * 
6920  * Return value: %TRUE if the input focus is within this GtkWindow
6921  *
6922  * Since: 2.4
6923  **/
6924 gboolean
6925 gtk_window_has_toplevel_focus (GtkWindow *window)
6926 {
6927   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6928
6929   return window->has_toplevel_focus;
6930 }
6931
6932 static void
6933 gtk_window_group_class_init (GtkWindowGroupClass *klass)
6934 {
6935 }
6936
6937 GType
6938 gtk_window_group_get_type (void)
6939 {
6940   static GType window_group_type = 0;
6941
6942   if (!window_group_type)
6943     {
6944       static const GTypeInfo window_group_info =
6945       {
6946         sizeof (GtkWindowGroupClass),
6947         NULL,           /* base_init */
6948         NULL,           /* base_finalize */
6949         (GClassInitFunc) gtk_window_group_class_init,
6950         NULL,           /* class_finalize */
6951         NULL,           /* class_data */
6952         sizeof (GtkWindowGroup),
6953         0,              /* n_preallocs */
6954         (GInstanceInitFunc) NULL,
6955       };
6956
6957       window_group_type = g_type_register_static (G_TYPE_OBJECT, I_("GtkWindowGroup"), 
6958                                                   &window_group_info, 0);
6959     }
6960
6961   return window_group_type;
6962 }
6963
6964 /**
6965  * gtk_window_group_new:
6966  * 
6967  * Creates a new #GtkWindowGroup object. Grabs added with
6968  * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
6969  * 
6970  * Return value: a new #GtkWindowGroup. 
6971  **/
6972 GtkWindowGroup *
6973 gtk_window_group_new (void)
6974 {
6975   return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
6976 }
6977
6978 static void
6979 window_group_cleanup_grabs (GtkWindowGroup *group,
6980                             GtkWindow      *window)
6981 {
6982   GSList *tmp_list;
6983   GSList *to_remove = NULL;
6984
6985   tmp_list = group->grabs;
6986   while (tmp_list)
6987     {
6988       if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
6989         to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
6990       tmp_list = tmp_list->next;
6991     }
6992
6993   while (to_remove)
6994     {
6995       gtk_grab_remove (to_remove->data);
6996       g_object_unref (to_remove->data);
6997       to_remove = g_slist_delete_link (to_remove, to_remove);
6998     }
6999 }
7000
7001 /**
7002  * gtk_window_group_add_window:
7003  * @window_group: a #GtkWindowGroup
7004  * @window: the #GtkWindow to add
7005  * 
7006  * Adds a window to a #GtkWindowGroup. 
7007  **/
7008 void
7009 gtk_window_group_add_window (GtkWindowGroup *window_group,
7010                              GtkWindow      *window)
7011 {
7012   g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
7013   g_return_if_fail (GTK_IS_WINDOW (window));
7014
7015   if (window->group != window_group)
7016     {
7017       g_object_ref (window);
7018       g_object_ref (window_group);
7019       
7020       if (window->group)
7021         gtk_window_group_remove_window (window->group, window);
7022       else
7023         window_group_cleanup_grabs (_gtk_window_get_group (NULL), window);
7024
7025       window->group = window_group;
7026
7027       g_object_unref (window);
7028     }
7029 }
7030
7031 /**
7032  * gtk_window_group_remove_window:
7033  * @window_group: a #GtkWindowGroup
7034  * @window: the #GtkWindow to remove
7035  * 
7036  * Removes a window from a #GtkWindowGroup.
7037  **/
7038 void
7039 gtk_window_group_remove_window (GtkWindowGroup *window_group,
7040                                 GtkWindow      *window)
7041 {
7042   g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
7043   g_return_if_fail (GTK_IS_WIDGET (window));
7044   g_return_if_fail (window->group == window_group);
7045
7046   g_object_ref (window);
7047
7048   window_group_cleanup_grabs (window_group, window);
7049   window->group = NULL;
7050   
7051   g_object_unref (window_group);
7052   g_object_unref (window);
7053 }
7054
7055 /* Return the group for the window or the default group
7056  */
7057 GtkWindowGroup *
7058 _gtk_window_get_group (GtkWindow *window)
7059 {
7060   if (window && window->group)
7061     return window->group;
7062   else
7063     {
7064       static GtkWindowGroup *default_group = NULL;
7065
7066       if (!default_group)
7067         default_group = gtk_window_group_new ();
7068
7069       return default_group;
7070     }
7071 }
7072
7073 /* Return the current grab widget of the given group 
7074  */
7075 GtkWidget *
7076 _gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
7077 {
7078   if (window_group->grabs)
7079     return GTK_WIDGET (window_group->grabs->data);
7080   return NULL;
7081 }
7082
7083 /*
7084   Derived from XParseGeometry() in XFree86  
7085
7086   Copyright 1985, 1986, 1987,1998  The Open Group
7087
7088   All Rights Reserved.
7089
7090   The above copyright notice and this permission notice shall be included
7091   in all copies or substantial portions of the Software.
7092
7093   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
7094   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
7095   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
7096   IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
7097   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
7098   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
7099   OTHER DEALINGS IN THE SOFTWARE.
7100
7101   Except as contained in this notice, the name of The Open Group shall
7102   not be used in advertising or otherwise to promote the sale, use or
7103   other dealings in this Software without prior written authorization
7104   from The Open Group.
7105 */
7106
7107
7108 /*
7109  *    XParseGeometry parses strings of the form
7110  *   "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
7111  *   width, height, xoffset, and yoffset are unsigned integers.
7112  *   Example:  "=80x24+300-49"
7113  *   The equal sign is optional.
7114  *   It returns a bitmask that indicates which of the four values
7115  *   were actually found in the string.  For each value found,
7116  *   the corresponding argument is updated;  for each value
7117  *   not found, the corresponding argument is left unchanged. 
7118  */
7119
7120 /* The following code is from Xlib, and is minimally modified, so we
7121  * can track any upstream changes if required.  Don't change this
7122  * code. Or if you do, put in a huge comment marking which thing
7123  * changed.
7124  */
7125
7126 static int
7127 read_int (gchar   *string,
7128           gchar  **next)
7129 {
7130   int result = 0;
7131   int sign = 1;
7132   
7133   if (*string == '+')
7134     string++;
7135   else if (*string == '-')
7136     {
7137       string++;
7138       sign = -1;
7139     }
7140
7141   for (; (*string >= '0') && (*string <= '9'); string++)
7142     {
7143       result = (result * 10) + (*string - '0');
7144     }
7145
7146   *next = string;
7147
7148   if (sign >= 0)
7149     return (result);
7150   else
7151     return (-result);
7152 }
7153
7154 /* 
7155  * Bitmask returned by XParseGeometry().  Each bit tells if the corresponding
7156  * value (x, y, width, height) was found in the parsed string.
7157  */
7158 #define NoValue         0x0000
7159 #define XValue          0x0001
7160 #define YValue          0x0002
7161 #define WidthValue      0x0004
7162 #define HeightValue     0x0008
7163 #define AllValues       0x000F
7164 #define XNegative       0x0010
7165 #define YNegative       0x0020
7166
7167 /* Try not to reformat/modify, so we can compare/sync with X sources */
7168 static int
7169 gtk_XParseGeometry (const char   *string,
7170                     int          *x,
7171                     int          *y,
7172                     unsigned int *width,   
7173                     unsigned int *height)  
7174 {
7175   int mask = NoValue;
7176   char *strind;
7177   unsigned int tempWidth, tempHeight;
7178   int tempX, tempY;
7179   char *nextCharacter;
7180
7181   /* These initializations are just to silence gcc */
7182   tempWidth = 0;
7183   tempHeight = 0;
7184   tempX = 0;
7185   tempY = 0;
7186   
7187   if ( (string == NULL) || (*string == '\0')) return(mask);
7188   if (*string == '=')
7189     string++;  /* ignore possible '=' at beg of geometry spec */
7190
7191   strind = (char *)string;
7192   if (*strind != '+' && *strind != '-' && *strind != 'x') {
7193     tempWidth = read_int(strind, &nextCharacter);
7194     if (strind == nextCharacter) 
7195       return (0);
7196     strind = nextCharacter;
7197     mask |= WidthValue;
7198   }
7199
7200   if (*strind == 'x' || *strind == 'X') {       
7201     strind++;
7202     tempHeight = read_int(strind, &nextCharacter);
7203     if (strind == nextCharacter)
7204       return (0);
7205     strind = nextCharacter;
7206     mask |= HeightValue;
7207   }
7208
7209   if ((*strind == '+') || (*strind == '-')) {
7210     if (*strind == '-') {
7211       strind++;
7212       tempX = -read_int(strind, &nextCharacter);
7213       if (strind == nextCharacter)
7214         return (0);
7215       strind = nextCharacter;
7216       mask |= XNegative;
7217
7218     }
7219     else
7220       { strind++;
7221       tempX = read_int(strind, &nextCharacter);
7222       if (strind == nextCharacter)
7223         return(0);
7224       strind = nextCharacter;
7225       }
7226     mask |= XValue;
7227     if ((*strind == '+') || (*strind == '-')) {
7228       if (*strind == '-') {
7229         strind++;
7230         tempY = -read_int(strind, &nextCharacter);
7231         if (strind == nextCharacter)
7232           return(0);
7233         strind = nextCharacter;
7234         mask |= YNegative;
7235
7236       }
7237       else
7238         {
7239           strind++;
7240           tempY = read_int(strind, &nextCharacter);
7241           if (strind == nextCharacter)
7242             return(0);
7243           strind = nextCharacter;
7244         }
7245       mask |= YValue;
7246     }
7247   }
7248         
7249   /* If strind isn't at the end of the string the it's an invalid
7250                 geometry specification. */
7251
7252   if (*strind != '\0') return (0);
7253
7254   if (mask & XValue)
7255     *x = tempX;
7256   if (mask & YValue)
7257     *y = tempY;
7258   if (mask & WidthValue)
7259     *width = tempWidth;
7260   if (mask & HeightValue)
7261     *height = tempHeight;
7262   return (mask);
7263 }
7264
7265 /**
7266  * gtk_window_parse_geometry:
7267  * @window: a #GtkWindow
7268  * @geometry: geometry string
7269  * 
7270  * Parses a standard X Window System geometry string - see the
7271  * manual page for X (type 'man X') for details on this.
7272  * gtk_window_parse_geometry() does work on all GTK+ ports
7273  * including Win32 but is primarily intended for an X environment.
7274  *
7275  * If either a size or a position can be extracted from the
7276  * geometry string, gtk_window_parse_geometry() returns %TRUE
7277  * and calls gtk_window_set_default_size() and/or gtk_window_move()
7278  * to resize/move the window.
7279  *
7280  * If gtk_window_parse_geometry() returns %TRUE, it will also
7281  * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
7282  * indicating to the window manager that the size/position of
7283  * the window was user-specified. This causes most window
7284  * managers to honor the geometry.
7285  *
7286  * Note that for gtk_window_parse_geometry() to work as expected, it has
7287  * to be called when the window has its "final" size, i.e. after calling
7288  * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
7289  * on the window.
7290  * 
7291  * <informalexample><programlisting>
7292  * #include &lt;gtk/gtk.h&gt;
7293  *    
7294  * static void
7295  * fill_with_content (GtkWidget *vbox)
7296  * {
7297  *   /<!-- -->* fill with content... *<!-- -->/
7298  * }
7299  *    
7300  * int
7301  * main (int argc, char *argv[])
7302  * {
7303  *   GtkWidget *window, *vbox;
7304  *   GdkGeometry size_hints = {
7305  *     100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST  
7306  *   };
7307  *    
7308  *   gtk_init (&amp;argc, &amp;argv);
7309  *   
7310  *   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7311  *   vbox = gtk_vbox_new (FALSE, 0);
7312  *   
7313  *   gtk_container_add (GTK_CONTAINER (window), vbox);
7314  *   fill_with_content (vbox);
7315  *   gtk_widget_show_all (vbox);
7316  *   
7317  *   gtk_window_set_geometry_hints (GTK_WINDOW (window),
7318  *                                  window,
7319  *                                  &amp;size_hints,
7320  *                                  GDK_HINT_MIN_SIZE | 
7321  *                                  GDK_HINT_BASE_SIZE | 
7322  *                                  GDK_HINT_RESIZE_INC);
7323  *   
7324  *   if (argc &gt; 1)
7325  *     {
7326  *       if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
7327  *         fprintf (stderr, "Failed to parse '&percnt;s'\n", argv[1]);
7328  *     }
7329  *    
7330  *   gtk_widget_show_all (window);
7331  *   gtk_main ();
7332  *    
7333  *   return 0;
7334  * }
7335  * </programlisting></informalexample>
7336  *
7337  * Return value: %TRUE if string was parsed successfully
7338  **/
7339 gboolean
7340 gtk_window_parse_geometry (GtkWindow   *window,
7341                            const gchar *geometry)
7342 {
7343   gint result, x = 0, y = 0;
7344   guint w, h;
7345   GdkGravity grav;
7346   gboolean size_set, pos_set;
7347   GdkScreen *screen;
7348   
7349   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7350   g_return_val_if_fail (geometry != NULL, FALSE);
7351
7352   screen = gtk_window_check_screen (window);
7353   
7354   result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
7355
7356   size_set = FALSE;
7357   if ((result & WidthValue) || (result & HeightValue))
7358     {
7359       gtk_window_set_default_size_internal (window, 
7360                                             TRUE, result & WidthValue ? w : -1,
7361                                             TRUE, result & HeightValue ? h : -1, 
7362                                             TRUE);
7363       size_set = TRUE;
7364     }
7365
7366   gtk_window_get_size (window, (gint *)&w, (gint *)&h);
7367   
7368   grav = GDK_GRAVITY_NORTH_WEST;
7369
7370   if ((result & XNegative) && (result & YNegative))
7371     grav = GDK_GRAVITY_SOUTH_EAST;
7372   else if (result & XNegative)
7373     grav = GDK_GRAVITY_NORTH_EAST;
7374   else if (result & YNegative)
7375     grav = GDK_GRAVITY_SOUTH_WEST;
7376
7377   if ((result & XValue) == 0)
7378     x = 0;
7379
7380   if ((result & YValue) == 0)
7381     y = 0;
7382
7383   if (grav == GDK_GRAVITY_SOUTH_WEST ||
7384       grav == GDK_GRAVITY_SOUTH_EAST)
7385     y = gdk_screen_get_height (screen) - h + y;
7386
7387   if (grav == GDK_GRAVITY_SOUTH_EAST ||
7388       grav == GDK_GRAVITY_NORTH_EAST)
7389     x = gdk_screen_get_width (screen) - w + x;
7390
7391   /* we don't let you put a window offscreen; maybe some people would
7392    * prefer to be able to, but it's kind of a bogus thing to do.
7393    */
7394   if (y < 0)
7395     y = 0;
7396
7397   if (x < 0)
7398     x = 0;
7399
7400   pos_set = FALSE;
7401   if ((result & XValue) || (result & YValue))
7402     {
7403       gtk_window_set_gravity (window, grav);
7404       gtk_window_move (window, x, y);
7405       pos_set = TRUE;
7406     }
7407
7408   if (size_set || pos_set)
7409     {
7410       /* Set USSize, USPosition hints */
7411       GtkWindowGeometryInfo *info;
7412
7413       info = gtk_window_get_geometry_info (window, TRUE);
7414
7415       if (pos_set)
7416         info->mask |= GDK_HINT_USER_POS;
7417       if (size_set)
7418         info->mask |= GDK_HINT_USER_SIZE;
7419     }
7420   
7421   return result != 0;
7422 }
7423
7424 static void
7425 gtk_window_mnemonic_hash_foreach (guint      keyval,
7426                                   GSList    *targets,
7427                                   gpointer   data)
7428 {
7429   struct {
7430     GtkWindow *window;
7431     GtkWindowKeysForeachFunc func;
7432     gpointer func_data;
7433   } *info = data;
7434
7435   (*info->func) (info->window, keyval, info->window->mnemonic_modifier, TRUE, info->func_data);
7436 }
7437
7438 void
7439 _gtk_window_keys_foreach (GtkWindow                *window,
7440                           GtkWindowKeysForeachFunc func,
7441                           gpointer                 func_data)
7442 {
7443   GSList *groups;
7444   GtkMnemonicHash *mnemonic_hash;
7445
7446   struct {
7447     GtkWindow *window;
7448     GtkWindowKeysForeachFunc func;
7449     gpointer func_data;
7450   } info;
7451
7452   info.window = window;
7453   info.func = func;
7454   info.func_data = func_data;
7455
7456   mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
7457   if (mnemonic_hash)
7458     _gtk_mnemonic_hash_foreach (mnemonic_hash,
7459                                 gtk_window_mnemonic_hash_foreach, &info);
7460
7461   groups = gtk_accel_groups_from_object (G_OBJECT (window));
7462   while (groups)
7463     {
7464       GtkAccelGroup *group = groups->data;
7465       gint i;
7466
7467       for (i = 0; i < group->n_accels; i++)
7468         {
7469           GtkAccelKey *key = &group->priv_accels[i].key;
7470           
7471           if (key->accel_key)
7472             (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
7473         }
7474       
7475       groups = groups->next;
7476     }
7477 }
7478
7479 static void
7480 gtk_window_keys_changed (GtkWindow *window)
7481 {
7482   gtk_window_free_key_hash (window);
7483   gtk_window_get_key_hash (window);
7484 }
7485
7486 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
7487
7488 struct _GtkWindowKeyEntry
7489 {
7490   guint keyval;
7491   guint modifiers;
7492   gboolean is_mnemonic;
7493 };
7494
7495 static void
7496 add_to_key_hash (GtkWindow      *window,
7497                  guint           keyval,
7498                  GdkModifierType modifiers,
7499                  gboolean        is_mnemonic,
7500                  gpointer        data)
7501 {
7502   GtkKeyHash *key_hash = data;
7503
7504   GtkWindowKeyEntry *entry = g_new (GtkWindowKeyEntry, 1);
7505
7506   entry->keyval = keyval;
7507   entry->modifiers = modifiers;
7508   entry->is_mnemonic = is_mnemonic;
7509
7510   /* GtkAccelGroup stores lowercased accelerators. To deal
7511    * with this, if <Shift> was specified, uppercase.
7512    */
7513   if (modifiers & GDK_SHIFT_MASK)
7514     {
7515       if (keyval == GDK_Tab)
7516         keyval = GDK_ISO_Left_Tab;
7517       else
7518         keyval = gdk_keyval_to_upper (keyval);
7519     }
7520   
7521   _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
7522 }
7523
7524 static GtkKeyHash *
7525 gtk_window_get_key_hash (GtkWindow *window)
7526 {
7527   GdkScreen *screen = gtk_window_check_screen (window);
7528   GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
7529   
7530   if (key_hash)
7531     return key_hash;
7532   
7533   key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
7534                                 (GDestroyNotify)g_free);
7535   _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
7536   g_object_set_data (G_OBJECT (window), I_("gtk-window-key-hash"), key_hash);
7537
7538   return key_hash;
7539 }
7540
7541 static void
7542 gtk_window_free_key_hash (GtkWindow *window)
7543 {
7544   GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
7545   if (key_hash)
7546     {
7547       _gtk_key_hash_free (key_hash);
7548       g_object_set_data (G_OBJECT (window), "gtk-window-key-hash", NULL);
7549     }
7550 }
7551
7552 /**
7553  * gtk_window_activate_key:
7554  * @window:  a #GtkWindow
7555  * @event:   a #GdkEventKey
7556  *
7557  * Activates mnemonics and accelerators for this #GtkWindow. This is normally
7558  * called by the default ::key_press_event handler for toplevel windows,
7559  * however in some cases it may be useful to call this directly when
7560  * overriding the standard key handling for a toplevel window.
7561  * 
7562  * Return value: %TRUE if a mnemonic or accelerator was found and activated.
7563  **/
7564 gboolean
7565 gtk_window_activate_key (GtkWindow   *window,
7566                          GdkEventKey *event)
7567 {
7568   GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
7569   GtkWindowKeyEntry *found_entry = NULL;
7570
7571   if (!key_hash)
7572     {
7573       gtk_window_keys_changed (window);
7574       key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
7575     }
7576   
7577   if (key_hash)
7578     {
7579       GSList *entries = _gtk_key_hash_lookup (key_hash,
7580                                               event->hardware_keycode,
7581                                               event->state,
7582                                               gtk_accelerator_get_default_mod_mask (),
7583                                               event->group);
7584       GSList *tmp_list;
7585
7586       for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
7587         {
7588           GtkWindowKeyEntry *entry = tmp_list->data;
7589           if (entry->is_mnemonic)
7590             {
7591               found_entry = entry;
7592               break;
7593             }
7594         }
7595       
7596       if (!found_entry && entries)
7597         found_entry = entries->data;
7598
7599       g_slist_free (entries);
7600     }
7601
7602   if (found_entry)
7603     {
7604       if (found_entry->is_mnemonic)
7605         return gtk_window_mnemonic_activate (window, found_entry->keyval, found_entry->modifiers);
7606       else
7607         return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval, found_entry->modifiers);
7608     }
7609   else
7610     return FALSE;
7611 }
7612
7613 static void
7614 window_update_has_focus (GtkWindow *window)
7615 {
7616   GtkWidget *widget = GTK_WIDGET (window);
7617   gboolean has_focus = window->has_toplevel_focus && window->is_active;
7618   
7619   if (has_focus != window->has_focus)
7620     {
7621       window->has_focus = has_focus;
7622       
7623       if (has_focus)
7624         {
7625           if (window->focus_widget &&
7626               window->focus_widget != widget &&
7627               !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
7628             do_focus_change (window->focus_widget, TRUE);       
7629         }
7630       else
7631         {
7632           if (window->focus_widget &&
7633               window->focus_widget != widget &&
7634               GTK_WIDGET_HAS_FOCUS (window->focus_widget))
7635             do_focus_change (window->focus_widget, FALSE);
7636         }
7637     }
7638 }
7639
7640 /**
7641  * _gtk_window_set_is_active:
7642  * @window: a #GtkWindow
7643  * @is_active: %TRUE if the window is in the currently active toplevel
7644  * 
7645  * Internal function that sets whether the #GtkWindow is part
7646  * of the currently active toplevel window (taking into account inter-process
7647  * embedding.)
7648  **/
7649 void
7650 _gtk_window_set_is_active (GtkWindow *window,
7651                            gboolean   is_active)
7652 {
7653   g_return_if_fail (GTK_IS_WINDOW (window));
7654
7655   is_active = is_active != FALSE;
7656
7657   if (is_active != window->is_active)
7658     {
7659       window->is_active = is_active;
7660       window_update_has_focus (window);
7661
7662       g_object_notify (G_OBJECT (window), "is-active");
7663     }
7664 }
7665
7666 /**
7667  * _gtk_window_set_has_toplevel_focus:
7668  * @window: a #GtkWindow
7669  * @has_toplevel_focus: %TRUE if the in
7670  * 
7671  * Internal function that sets whether the keyboard focus for the
7672  * toplevel window (taking into account inter-process embedding.)
7673  **/
7674 void
7675 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
7676                                    gboolean   has_toplevel_focus)
7677 {
7678   g_return_if_fail (GTK_IS_WINDOW (window));
7679   
7680   has_toplevel_focus = has_toplevel_focus != FALSE;
7681
7682   if (has_toplevel_focus != window->has_toplevel_focus)
7683     {
7684       window->has_toplevel_focus = has_toplevel_focus;
7685       window_update_has_focus (window);
7686
7687       g_object_notify (G_OBJECT (window), "has-toplevel-focus");
7688     }
7689 }
7690
7691 /**
7692  * gtk_window_set_auto_startup_notification:
7693  * @setting: %TRUE to automatically do startup notification
7694  *
7695  * By default, after showing the first #GtkWindow for each #GdkScreen,
7696  * GTK+ calls gdk_screen_notify_startup_complete().  Call this
7697  * function to disable the automatic startup notification. You might
7698  * do this if your first window is a splash screen, and you want to
7699  * delay notification until after your real main window has been
7700  * shown, for example.
7701  *
7702  * In that example, you would disable startup notification
7703  * temporarily, show your splash screen, then re-enable it so that
7704  * showing the main window would automatically result in notification.
7705  * 
7706  * Since: 2.2
7707  **/
7708 void
7709 gtk_window_set_auto_startup_notification (gboolean setting)
7710 {
7711   disable_startup_notification = !setting;
7712 }
7713
7714 #ifdef G_OS_WIN32
7715
7716 #undef gtk_window_set_icon_from_file
7717
7718 gboolean
7719 gtk_window_set_icon_from_file (GtkWindow   *window,
7720                                const gchar *filename,
7721                                GError     **err)
7722 {
7723   gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, err);
7724   gboolean retval;
7725
7726   if (utf8_filename == NULL)
7727     return FALSE;
7728
7729   retval = gtk_window_set_icon_from_file_utf8 (window, utf8_filename, err);
7730
7731   g_free (utf8_filename);
7732
7733   return retval;
7734 }
7735
7736 #undef gtk_window_set_default_icon_from_file
7737
7738 gboolean
7739 gtk_window_set_default_icon_from_file (const gchar *filename,
7740                                        GError     **err)
7741 {
7742   gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, err);
7743   gboolean retval;
7744
7745   if (utf8_filename == NULL)
7746     return FALSE;
7747
7748   retval = gtk_window_set_default_icon_from_file_utf8 (utf8_filename, err);
7749
7750   g_free (utf8_filename);
7751
7752   return retval;
7753 }
7754
7755 #endif
7756
7757 #define __GTK_WINDOW_C__
7758 #include "gtkaliasdef.c"