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