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