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