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