]> Pileus Git - ~andy/gtk/blob - gtk/gtkwindow.c
213cb1b245a9823b9254d99d1fe80ff0bc97b487
[~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 <string.h>
28 #include <limits.h>
29 #include "gdk/gdk.h"
30 #include "gdk/gdkkeysyms.h"
31
32 #if defined (GDK_WINDOWING_X11)
33 #include "x11/gdkx.h"
34 #elif defined (GDK_WINDOWING_WIN32)
35 #include "win32/gdkwin32.h"
36 #elif defined (GDK_WINDOWING_NANOX)
37 #include "nanox/gdkprivate-nanox.h"
38 #elif defined (GDK_WINDOWING_FB)
39 #include "linux-fb/gdkfb.h"
40 #endif
41
42 #include "gtkprivate.h"
43 #include "gtkrc.h"
44 #include "gtksignal.h"
45 #include "gtkwindow.h"
46 #include "gtkwindow-decorate.h"
47 #include "gtkbindings.h"
48 #include "gtkmain.h"
49 #include "gtkiconfactory.h"
50 #include "gtkintl.h"
51
52 enum {
53   SET_FOCUS,
54   FRAME_EVENT,
55   ACTIVATE_FOCUS,
56   ACTIVATE_DEFAULT,
57   MOVE_FOCUS,
58   LAST_SIGNAL
59 };
60
61 enum {
62   PROP_0,
63
64   /* Construct */
65   PROP_TYPE,
66
67   /* Style Props */
68   PROP_TITLE,
69   PROP_AUTO_SHRINK,
70   PROP_ALLOW_SHRINK,
71   PROP_ALLOW_GROW,
72   PROP_RESIZABLE,
73   PROP_MODAL,
74   PROP_WIN_POS,
75   PROP_DEFAULT_WIDTH,
76   PROP_DEFAULT_HEIGHT,
77   PROP_DESTROY_WITH_PARENT,
78
79   LAST_ARG
80 };
81
82 typedef struct {
83   GdkGeometry    geometry; /* Last set of geometry hints we set */
84   GdkWindowHints flags;
85   gint           width;
86   gint           height;
87 } GtkWindowLastGeometryInfo;
88
89 struct _GtkWindowGeometryInfo
90 {
91   /* Properties that the app has set on the window
92    */
93   GdkGeometry    geometry;      /* Geometry hints */
94   GdkWindowHints mask;
95   GtkWidget     *widget;        /* subwidget to which hints apply */
96   gint           width;         /* Default size */
97   gint           height;
98   guint          may_shrink : 1; /* one-shot auto_shrink behaviour after set_default_size */
99
100   GtkWindowLastGeometryInfo last;
101 };
102
103 typedef struct {
104   GtkWindow *window;
105   guint keyval;
106
107   GSList *targets;
108 } GtkWindowMnemonic;
109
110
111 static void gtk_window_class_init         (GtkWindowClass    *klass);
112 static void gtk_window_init               (GtkWindow         *window);
113 static void gtk_window_dispose            (GObject           *object);
114 static void gtk_window_destroy            (GtkObject         *object);
115 static void gtk_window_finalize           (GObject           *object);
116 static void gtk_window_show               (GtkWidget         *widget);
117 static void gtk_window_hide               (GtkWidget         *widget);
118 static void gtk_window_map                (GtkWidget         *widget);
119 static void gtk_window_unmap              (GtkWidget         *widget);
120 static void gtk_window_realize            (GtkWidget         *widget);
121 static void gtk_window_unrealize          (GtkWidget         *widget);
122 static void gtk_window_size_request       (GtkWidget         *widget,
123                                            GtkRequisition    *requisition);
124 static void gtk_window_size_allocate      (GtkWidget         *widget,
125                                            GtkAllocation     *allocation);
126 static gint gtk_window_event              (GtkWidget *widget,
127                                            GdkEvent *event);
128 static gboolean gtk_window_frame_event    (GtkWidget *widget,
129                                            GdkEvent *event);
130 static gint gtk_window_configure_event    (GtkWidget         *widget,
131                                            GdkEventConfigure *event);
132 static gint gtk_window_key_press_event    (GtkWidget         *widget,
133                                            GdkEventKey       *event);
134 static gint gtk_window_key_release_event  (GtkWidget         *widget,
135                                            GdkEventKey       *event);
136 static gint gtk_window_enter_notify_event (GtkWidget         *widget,
137                                            GdkEventCrossing  *event);
138 static gint gtk_window_leave_notify_event (GtkWidget         *widget,
139                                            GdkEventCrossing  *event);
140 static gint gtk_window_focus_in_event     (GtkWidget         *widget,
141                                            GdkEventFocus     *event);
142 static gint gtk_window_focus_out_event    (GtkWidget         *widget,
143                                            GdkEventFocus     *event);
144 static gint gtk_window_client_event       (GtkWidget         *widget,
145                                            GdkEventClient    *event);
146 static void gtk_window_check_resize       (GtkContainer      *container);
147 static gint gtk_window_focus              (GtkWidget        *widget,
148                                            GtkDirectionType  direction);
149 static void gtk_window_real_set_focus     (GtkWindow         *window,
150                                            GtkWidget         *focus);
151
152 static void gtk_window_real_activate_default (GtkWindow         *window);
153 static void gtk_window_real_activate_focus   (GtkWindow         *window);
154 static void gtk_window_move_focus            (GtkWindow         *window,
155                                               GtkDirectionType   dir);
156
157 static void gtk_window_move_resize        (GtkWindow         *window);
158 static gboolean gtk_window_compare_hints  (GdkGeometry       *geometry_a,
159                                            guint              flags_a,
160                                            GdkGeometry       *geometry_b,
161                                            guint              flags_b);
162 static void gtk_window_compute_default_size (GtkWindow       *window,
163                                              guint           *width,
164                                              guint           *height);
165 static void  gtk_window_constrain_size      (GtkWindow       *window,
166                                              GdkGeometry     *geometry,
167                                              guint            flags,
168                                              gint             width,
169                                              gint             height,
170                                              gint            *new_width,
171                                              gint            *new_height);
172 static void gtk_window_compute_hints      (GtkWindow         *window, 
173                                            GdkGeometry       *new_geometry,
174                                            guint             *new_flags);
175 static gint gtk_window_compute_reposition (GtkWindow         *window,
176                                            gint               new_width,
177                                            gint               new_height,
178                                            gint              *x,
179                                            gint              *y);
180
181 static void gtk_window_read_rcfiles       (GtkWidget         *widget,
182                                            GdkEventClient    *event);
183 static void gtk_window_paint              (GtkWidget         *widget,
184                                            GdkRectangle      *area);
185 static gint gtk_window_expose             (GtkWidget         *widget,
186                                            GdkEventExpose    *event);
187 static void gtk_window_unset_transient_for         (GtkWindow  *window);
188 static void gtk_window_transient_parent_realized   (GtkWidget  *parent,
189                                                     GtkWidget  *window);
190 static void gtk_window_transient_parent_unrealized (GtkWidget  *parent,
191                                                     GtkWidget  *window);
192
193 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
194                                                             gboolean   create);
195
196
197 static GSList      *toplevel_list = NULL;
198 static GHashTable  *mnemonic_hash_table = NULL;
199 static GtkBinClass *parent_class = NULL;
200 static guint        window_signals[LAST_SIGNAL] = { 0 };
201
202 static void gtk_window_set_property (GObject         *object,
203                                      guint            prop_id,
204                                      const GValue    *value,
205                                      GParamSpec      *pspec);
206 static void gtk_window_get_property (GObject         *object,
207                                      guint            prop_id,
208                                      GValue          *value,
209                                      GParamSpec      *pspec);
210
211
212 static guint
213 mnemonic_hash (gconstpointer key)
214 {
215   const GtkWindowMnemonic *k;
216   guint h;
217   
218   k = (GtkWindowMnemonic *)key;
219   
220   h = (gulong) k->window;
221   h ^= k->keyval << 16;
222   h ^= k->keyval >> 16;
223
224   return h;
225 }
226
227 static gboolean
228 mnemonic_equal (gconstpointer a, gconstpointer b)
229 {
230   const GtkWindowMnemonic *ka;
231   const GtkWindowMnemonic *kb;
232   
233   ka = (GtkWindowMnemonic *)a;
234   kb = (GtkWindowMnemonic *)b;
235
236   return
237     (ka->window == kb->window) &&
238     (ka->keyval == kb->keyval);
239 }
240
241 GtkType
242 gtk_window_get_type (void)
243 {
244   static GtkType window_type = 0;
245
246   if (!window_type)
247     {
248       static const GtkTypeInfo window_info =
249       {
250         "GtkWindow",
251         sizeof (GtkWindow),
252         sizeof (GtkWindowClass),
253         (GtkClassInitFunc) gtk_window_class_init,
254         (GtkObjectInitFunc) gtk_window_init,
255         /* reserved_1 */ NULL,
256         /* reserved_2 */ NULL,
257         (GtkClassInitFunc) NULL,
258       };
259
260       window_type = gtk_type_unique (gtk_bin_get_type (), &window_info);
261     }
262
263   return window_type;
264 }
265
266 static void
267 gtk_window_class_init (GtkWindowClass *klass)
268 {
269   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
270   GtkObjectClass *object_class;
271   GtkWidgetClass *widget_class;
272   GtkContainerClass *container_class;
273   GtkBindingSet *binding_set;
274   
275   object_class = (GtkObjectClass*) klass;
276   widget_class = (GtkWidgetClass*) klass;
277   container_class = (GtkContainerClass*) klass;
278   
279   parent_class = gtk_type_class (gtk_bin_get_type ());
280
281   gobject_class->dispose = gtk_window_dispose;
282   gobject_class->finalize = gtk_window_finalize;
283
284   gobject_class->set_property = gtk_window_set_property;
285   gobject_class->get_property = gtk_window_get_property;
286   
287   object_class->destroy = gtk_window_destroy;
288
289   widget_class->show = gtk_window_show;
290   widget_class->hide = gtk_window_hide;
291   widget_class->map = gtk_window_map;
292   widget_class->unmap = gtk_window_unmap;
293   widget_class->realize = gtk_window_realize;
294   widget_class->unrealize = gtk_window_unrealize;
295   widget_class->size_request = gtk_window_size_request;
296   widget_class->size_allocate = gtk_window_size_allocate;
297   widget_class->configure_event = gtk_window_configure_event;
298   widget_class->key_press_event = gtk_window_key_press_event;
299   widget_class->key_release_event = gtk_window_key_release_event;
300   widget_class->enter_notify_event = gtk_window_enter_notify_event;
301   widget_class->leave_notify_event = gtk_window_leave_notify_event;
302   widget_class->focus_in_event = gtk_window_focus_in_event;
303   widget_class->focus_out_event = gtk_window_focus_out_event;
304   widget_class->client_event = gtk_window_client_event;
305   widget_class->focus = gtk_window_focus;
306   
307   widget_class->expose_event = gtk_window_expose;
308    
309   container_class->check_resize = gtk_window_check_resize;
310
311   klass->set_focus = gtk_window_real_set_focus;
312   klass->frame_event = gtk_window_frame_event;
313
314   klass->activate_default = gtk_window_real_activate_default;
315   klass->activate_focus = gtk_window_real_activate_focus;
316   klass->move_focus = gtk_window_move_focus;
317   
318   /* Construct */
319   g_object_class_install_property (gobject_class,
320                                    PROP_TYPE,
321                                    g_param_spec_enum ("type",
322                                                       _("Window Type"),
323                                                       _("The type of the window"),
324                                                       GTK_TYPE_WINDOW_TYPE,
325                                                       GTK_WINDOW_TOPLEVEL,
326                                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
327
328   /* Style Props */
329   g_object_class_install_property (gobject_class,
330                                    PROP_TITLE,
331                                    g_param_spec_string ("title",
332                                                         _("Window Title"),
333                                                         _("The title of the window"),
334                                                         NULL,
335                                                         G_PARAM_READWRITE));
336
337   g_object_class_install_property (gobject_class,
338                                    PROP_AUTO_SHRINK,
339                                    g_param_spec_boolean ("auto_shrink",
340                                                          _("Auto Shrink"),
341                                                          _("If TRUE, the window automatically shrinks to its size request anytime a resize occurs. Don't use this feature, it makes no sense."),
342                                                          FALSE,
343                                                          G_PARAM_READWRITE));
344
345   g_object_class_install_property (gobject_class,
346                                    PROP_ALLOW_SHRINK,
347                                    g_param_spec_boolean ("allow_shrink",
348                                                          _("Allow Shrink"),
349                                                          _("If TRUE, the window has no mimimum size. Don't use this feature, it makes no sense."),
350                                                          FALSE,
351                                                          G_PARAM_READWRITE));
352
353   g_object_class_install_property (gobject_class,
354                                    PROP_ALLOW_GROW,
355                                    g_param_spec_boolean ("allow_grow",
356                                                          _("Allow Grow"),
357                                                          _("If TRUE, users can expand the window beyond its minimum size."),
358                                                          TRUE,
359                                                          G_PARAM_READWRITE));
360
361   g_object_class_install_property (gobject_class,
362                                    PROP_RESIZABLE,
363                                    g_param_spec_boolean ("resizable",
364                                                          _("Resizable"),
365                                                          _("If TRUE, users can resize the window."),
366                                                          TRUE,
367                                                          G_PARAM_READWRITE));
368   
369   g_object_class_install_property (gobject_class,
370                                    PROP_MODAL,
371                                    g_param_spec_boolean ("modal",
372                                                          _("Modal"),
373                                                          _("If TRUE, the window is modal (other windows are not usable while this one is up)."),
374                                                          FALSE,
375                                                          G_PARAM_READWRITE));
376
377   g_object_class_install_property (gobject_class,
378                                    PROP_WIN_POS,
379                                    g_param_spec_enum ("window_position",
380                                                       _("Window Position"),
381                                                       _("The initial position of the window."),
382                                                       GTK_TYPE_WINDOW_POSITION,
383                                                       GTK_WIN_POS_NONE,
384                                                       G_PARAM_READWRITE));
385  
386   g_object_class_install_property (gobject_class,
387                                    PROP_DEFAULT_WIDTH,
388                                    g_param_spec_int ("default_width",
389                                                      _("Default Width"),
390                                                      _("The default width of the window, or 0 to use the size request."),
391                                                      0,
392                                                      G_MAXINT,
393                                                      0,
394                                                      G_PARAM_READWRITE));
395  
396   g_object_class_install_property (gobject_class,
397                                    PROP_DEFAULT_HEIGHT,
398                                    g_param_spec_int ("default_height",
399                                                      _("Default Height"),
400                                                      _("The default height of the window, or 0 to use the size request."),
401                                                      0,
402                                                      G_MAXINT,
403                                                      0,
404                                                      G_PARAM_READWRITE));
405  
406   g_object_class_install_property (gobject_class,
407                                    PROP_DESTROY_WITH_PARENT,
408                                    g_param_spec_boolean ("destroy_with_parent",
409                                                          _("Destroy with Parent"),
410                                                          _("If this window should be destroyed when the parent is destroyed"),
411                                                          FALSE,
412                                                          G_PARAM_READWRITE));
413
414   /* Style props are set or not */
415
416   window_signals[SET_FOCUS] =
417     g_signal_new ("set_focus",
418                   G_TYPE_FROM_CLASS (object_class),
419                   G_SIGNAL_RUN_LAST,
420                   G_STRUCT_OFFSET (GtkWindowClass, set_focus),
421                   NULL, NULL,
422                   gtk_marshal_VOID__OBJECT,
423                   G_TYPE_NONE, 1,
424                   GTK_TYPE_WIDGET);
425   
426   window_signals[FRAME_EVENT] =
427     g_signal_new ("frame_event",
428                   G_TYPE_FROM_CLASS(object_class),
429                   G_SIGNAL_RUN_LAST,
430                   G_STRUCT_OFFSET(GtkWindowClass, frame_event),
431                   _gtk_boolean_handled_accumulator, NULL,
432                   gtk_marshal_BOOLEAN__BOXED,
433                   G_TYPE_BOOLEAN, 1,
434                   GDK_TYPE_EVENT);
435
436   window_signals[ACTIVATE_FOCUS] =
437     g_signal_new ("activate_focus",
438                   G_OBJECT_CLASS_TYPE (object_class),
439                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
440                   GTK_SIGNAL_OFFSET (GtkWindowClass, activate_focus),
441                   NULL, NULL,
442                   gtk_marshal_VOID__VOID,
443                   G_TYPE_NONE,
444                   0);
445
446   window_signals[ACTIVATE_DEFAULT] =
447     g_signal_new ("activate_default",
448                   G_OBJECT_CLASS_TYPE (object_class),
449                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
450                   GTK_SIGNAL_OFFSET (GtkWindowClass, activate_default),
451                   NULL, NULL,
452                   gtk_marshal_VOID__VOID,
453                   G_TYPE_NONE,
454                   0);
455
456   window_signals[MOVE_FOCUS] =
457     g_signal_new ("move_focus",
458                   G_OBJECT_CLASS_TYPE (object_class),
459                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
460                   GTK_SIGNAL_OFFSET (GtkWindowClass, move_focus),
461                   NULL, NULL,
462                   gtk_marshal_VOID__ENUM,
463                   G_TYPE_NONE,
464                   1,
465                   GTK_TYPE_DIRECTION_TYPE);
466   
467   if (!mnemonic_hash_table)
468     mnemonic_hash_table = g_hash_table_new (mnemonic_hash,
469                                             mnemonic_equal);
470
471   /*
472    * Key bindings
473    */
474
475   binding_set = gtk_binding_set_by_class (klass);
476
477   gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
478                                 "activate_focus", 0);
479   gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0,
480                                 "activate_focus", 0);
481   
482   gtk_binding_entry_add_signal (binding_set, GDK_Return, 0,
483                                 "activate_default", 0);
484
485   gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
486                                 "activate_default", 0);
487
488   gtk_binding_entry_add_signal (binding_set, GDK_Up, 0,
489                                 "move_focus", 1,
490                                 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_UP);
491   gtk_binding_entry_add_signal (binding_set, GDK_KP_Up, 0,
492                                 "move_focus", 1,
493                                 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_UP);
494
495   gtk_binding_entry_add_signal (binding_set, GDK_Down, 0,
496                                 "move_focus", 1,
497                                 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_DOWN);
498   gtk_binding_entry_add_signal (binding_set, GDK_KP_Down, 0,
499                                 "move_focus", 1,
500                                 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_DOWN);
501
502   gtk_binding_entry_add_signal (binding_set, GDK_Left, 0,
503                                 "move_focus", 1,
504                                 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_LEFT);
505   gtk_binding_entry_add_signal (binding_set, GDK_KP_Left, 0,
506                                 "move_focus", 1,
507                                 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_LEFT);  
508
509   gtk_binding_entry_add_signal (binding_set, GDK_Right, 0,
510                                 "move_focus", 1,
511                                 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_RIGHT);
512   gtk_binding_entry_add_signal (binding_set, GDK_KP_Right, 0,
513                                 "move_focus", 1,
514                                 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_RIGHT);  
515
516   gtk_binding_entry_add_signal (binding_set, GDK_Tab, 0,
517                                 "move_focus", 1,
518                                 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_FORWARD);
519   gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, 0,
520                                 "move_focus", 1,
521                                 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_FORWARD);
522   gtk_binding_entry_add_signal (binding_set, GDK_ISO_Left_Tab, 0,
523                                 "move_focus", 1,
524                                 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_FORWARD);
525
526   gtk_binding_entry_add_signal (binding_set, GDK_Tab, GDK_SHIFT_MASK,
527                                 "move_focus", 1,
528                                 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
529   gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, GDK_SHIFT_MASK,
530                                 "move_focus", 1,
531                                 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
532   gtk_binding_entry_add_signal (binding_set, GDK_ISO_Left_Tab, GDK_SHIFT_MASK,
533                                 "move_focus", 1,
534                                 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
535 }
536
537 static void
538 gtk_window_init (GtkWindow *window)
539 {
540   GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
541   GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
542
543   GTK_PRIVATE_SET_FLAG (window, GTK_ANCHORED);
544
545   gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
546
547   window->title = NULL;
548   window->wmclass_name = g_strdup (g_get_prgname ());
549   window->wmclass_class = g_strdup (gdk_progclass);
550   window->wm_role = NULL;
551   window->geometry_info = NULL;
552   window->type = GTK_WINDOW_TOPLEVEL;
553   window->focus_widget = NULL;
554   window->default_widget = NULL;
555   window->resize_count = 0;
556   window->allow_shrink = FALSE;
557   window->allow_grow = TRUE;
558   window->auto_shrink = FALSE;
559   window->handling_resize = FALSE;
560   window->position = GTK_WIN_POS_NONE;
561   window->use_uposition = TRUE;
562   window->modal = FALSE;
563   window->frame = NULL;
564   window->has_frame = FALSE;
565   window->frame_left = 0;
566   window->frame_right = 0;
567   window->frame_top = 0;
568   window->frame_bottom = 0;
569   window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
570   window->gravity = GDK_GRAVITY_NORTH_WEST;
571   window->decorated = TRUE;
572   window->mnemonic_modifier = GDK_MOD1_MASK;
573   
574   gtk_widget_ref (GTK_WIDGET (window));
575   gtk_object_sink (GTK_OBJECT (window));
576   window->has_user_ref_count = TRUE;
577   toplevel_list = g_slist_prepend (toplevel_list, window);
578
579   gtk_decorated_window_init (window);
580
581   gtk_signal_connect (GTK_OBJECT (window),
582                       "event",
583                       GTK_SIGNAL_FUNC (gtk_window_event),
584                       NULL);
585 }
586
587 static void
588 gtk_window_set_property (GObject      *object,
589                          guint         prop_id,
590                          const GValue *value,
591                          GParamSpec   *pspec)
592 {
593   GtkWindow  *window;
594
595   window = GTK_WINDOW (object);
596
597   switch (prop_id)
598     {
599     case PROP_TYPE:
600       window->type = g_value_get_enum (value);
601       break;
602     case PROP_TITLE:
603       gtk_window_set_title (window, g_value_get_string (value));
604       break;
605     case PROP_AUTO_SHRINK:
606       window->auto_shrink = g_value_get_boolean (value);
607       gtk_widget_queue_resize (GTK_WIDGET (window));
608       break;
609     case PROP_ALLOW_SHRINK:
610       window->allow_shrink = g_value_get_boolean (value);
611       gtk_widget_queue_resize (GTK_WIDGET (window));
612       break;
613     case PROP_ALLOW_GROW:
614       window->allow_grow = g_value_get_boolean (value);
615       gtk_widget_queue_resize (GTK_WIDGET (window));
616       g_object_notify (G_OBJECT (window), "resizable");
617       break;
618     case PROP_RESIZABLE:
619       window->allow_grow = g_value_get_boolean (value);
620       gtk_widget_queue_resize (GTK_WIDGET (window));
621       g_object_notify (G_OBJECT (window), "allow_grow");
622       break;
623     case PROP_MODAL:
624       gtk_window_set_modal (window, g_value_get_boolean (value));
625       break;
626     case PROP_WIN_POS:
627       gtk_window_set_position (window, g_value_get_enum (value));
628       break;
629     case PROP_DEFAULT_WIDTH:
630       gtk_window_set_default_size (window, g_value_get_int (value), -1);
631       break;
632     case PROP_DEFAULT_HEIGHT:
633       gtk_window_set_default_size (window, -1, g_value_get_int (value));
634       break;
635     case PROP_DESTROY_WITH_PARENT:
636       gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
637       break;
638     default:
639       break;
640     }
641 }
642
643 static void
644 gtk_window_get_property (GObject      *object,
645                          guint         prop_id,
646                          GValue       *value,
647                          GParamSpec   *pspec)
648 {
649   GtkWindow  *window;
650
651   window = GTK_WINDOW (object);
652
653   switch (prop_id)
654     {
655       GtkWindowGeometryInfo *info;
656     case PROP_TYPE:
657       g_value_set_enum (value, window->type);
658       break;
659     case PROP_TITLE:
660       g_value_set_string (value, window->title);
661       break;
662     case PROP_AUTO_SHRINK:
663       g_value_set_boolean (value, window->auto_shrink);
664       break;
665     case PROP_ALLOW_SHRINK:
666       g_value_set_boolean (value, window->allow_shrink);
667       break;
668     case PROP_ALLOW_GROW:
669       g_value_set_boolean (value, window->allow_grow);
670       break;
671     case PROP_RESIZABLE:
672       g_value_set_boolean (value, window->allow_grow);
673       break;
674     case PROP_MODAL:
675       g_value_set_boolean (value, window->modal);
676       break;
677     case PROP_WIN_POS:
678       g_value_set_enum (value, window->position);
679       break;
680     case PROP_DEFAULT_WIDTH:
681       info = gtk_window_get_geometry_info (window, FALSE);
682       if (!info)
683         g_value_set_int (value, 0);
684       else
685         g_value_set_int (value, info->width);
686       break;
687     case PROP_DEFAULT_HEIGHT:
688       info = gtk_window_get_geometry_info (window, FALSE);
689       if (!info)
690         g_value_set_int (value, 0);
691       else
692         g_value_set_int (value, info->height);
693       break;
694     case PROP_DESTROY_WITH_PARENT:
695       g_value_set_boolean (value, window->destroy_with_parent);
696       break;
697     default:
698       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
699       break;
700     }
701 }
702
703 /**
704  * gtk_window_new:
705  * @type: type of window
706  * 
707  * Creates a new #GtkWindow, which is a toplevel window that can
708  * contain other widgets. Nearly always, the type of the window should
709  * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
710  * popup menu from scratch (which is a bad idea, just use #GtkMenu),
711  * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
712  * dialogs, though in some other toolkits dialogs are called "popups."
713  * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
714  * Popup windows are not controlled by the window manager.
715  *
716  * If you simply want an undecorated window (no window borders), use
717  * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
718  * 
719  * Return value: a new #GtkWindow.
720  **/
721 GtkWidget*
722 gtk_window_new (GtkWindowType type)
723 {
724   GtkWindow *window;
725
726   g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
727
728   window = gtk_type_new (GTK_TYPE_WINDOW);
729
730   window->type = type;
731
732   return GTK_WIDGET (window);
733 }
734
735 /**
736  * gtk_window_set_title:
737  * @window: a #GtkWindow
738  * @title: title of the window
739  * 
740  * Sets the title of the #GtkWindow. The title of a window will be displayed in
741  * its title bar; on the X Window System, the title bar is rendered by the
742  * window manager, so exactly how the title appears to users may vary according
743  * to a user's exact configuration. The title should help a user distinguish
744  * this window from other windows they may have open. A good title might
745  * include the application name and current document filename, for example.
746  * 
747  **/
748 void
749 gtk_window_set_title (GtkWindow   *window,
750                       const gchar *title)
751 {
752   g_return_if_fail (window != NULL);
753   g_return_if_fail (GTK_IS_WINDOW (window));
754
755   if (window->title)
756     g_free (window->title);
757   window->title = g_strdup (title);
758
759   if (GTK_WIDGET_REALIZED (window))
760     {
761       gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
762
763       gtk_decorated_window_set_title (window, title);
764     }
765
766   g_object_notify (G_OBJECT (window), "title");
767 }
768
769 /**
770  * gtk_window_get_title:
771  * @window: a #GtkWindow
772  *
773  * Retrieves the title of the window. See gtk_window_set_title().
774  *
775  * Return value: the title of the window, or %NULL if none has
776  *    been set explicitely. The returned string is owned by the widget
777  *    and must not be modified or freed.
778  **/
779 G_CONST_RETURN gchar *
780 gtk_window_get_title (GtkWindow *window)
781 {
782   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
783
784   return window->title;
785 }
786
787 /**
788  * gtk_window_set_wmclass:
789  * @window: a #GtkWindow
790  * @wmclass_name: window name hint
791  * @wmclass_class: window class hint
792  *
793  * Don't use this function. It sets the X Window System "class" and
794  * "name" hints for a window.  According to the ICCCM, you should
795  * always set these to the same value for all windows in an
796  * application, and GTK sets them to that value by default, so calling
797  * this function is sort of pointless. However, you may want to call
798  * gtk_window_set_role() on each window in your application, for the
799  * benefit of the session manager. Setting the role allows the window
800  * manager to restore window positions when loading a saved session.
801  * 
802  **/
803 void
804 gtk_window_set_wmclass (GtkWindow *window,
805                         const gchar *wmclass_name,
806                         const gchar *wmclass_class)
807 {
808   g_return_if_fail (window != NULL);
809   g_return_if_fail (GTK_IS_WINDOW (window));
810
811   g_free (window->wmclass_name);
812   window->wmclass_name = g_strdup (wmclass_name);
813
814   g_free (window->wmclass_class);
815   window->wmclass_class = g_strdup (wmclass_class);
816
817   if (GTK_WIDGET_REALIZED (window))
818     g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
819 }
820
821 /**
822  * gtk_window_set_role:
823  * @window: a #GtkWindow
824  * @role: unique identifier for the window to be used when restoring a session
825  *
826  * In combination with the window title, the window role allows a
827  * window manager to identify "the same" window when an application is
828  * restarted. So for example you might set the "toolbox" role on your
829  * app's toolbox window, so that when the user restarts their session,
830  * the window manager can put the toolbox back in the same place.
831  *
832  * If a window already has a unique title, you don't need to set the
833  * role, since the WM can use the title to identify the window when
834  * restoring the session.
835  * 
836  **/
837 void
838 gtk_window_set_role (GtkWindow   *window,
839                      const gchar *role)
840 {
841   g_return_if_fail (GTK_IS_WINDOW (window));
842
843   if (role == window->wm_role)
844     return;
845   
846   g_free (window->wm_role);
847   window->wm_role = g_strdup (role);
848   
849   if (GTK_WIDGET_REALIZED (window))
850     g_warning ("gtk_window_set_role(): shouldn't set role after window is realized!\n");
851 }
852
853 /**
854  * gtk_window_get_role:
855  * @window: a #GtkWindow
856  *
857  * Returns the role of the window. See gtk_window_set_role() for
858  * further explanation.
859  *
860  * Return value: the role of the window if set, or %NULL. The
861  *   returned is owned by the widget and must not be modified
862  *   or freed.
863  **/
864 G_CONST_RETURN gchar *
865 gtk_window_get_role (GtkWindow *window)
866 {
867   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
868
869   return window->wm_role;
870 }
871
872 /**
873  * gtk_window_set_focus:
874  * @window: a #GtkWindow
875  * @focus: widget to be the new focus widget
876  *
877  * If @focus is not the current focus widget, and is focusable, emits
878  * the "set_focus" signal to set @focus as the focus widget for the
879  * window.  This function is more or less GTK-internal; to focus an
880  * entry widget or the like, you should use gtk_widget_grab_focus()
881  * instead of this function.
882  * 
883  **/
884 void
885 gtk_window_set_focus (GtkWindow *window,
886                       GtkWidget *focus)
887 {
888   g_return_if_fail (window != NULL);
889   g_return_if_fail (GTK_IS_WINDOW (window));
890   if (focus)
891     {
892       g_return_if_fail (GTK_IS_WIDGET (focus));
893       g_return_if_fail (GTK_WIDGET_CAN_FOCUS (focus));
894     }
895
896   if ((window->focus_widget != focus) ||
897       (focus && !GTK_WIDGET_HAS_FOCUS (focus)))
898     gtk_signal_emit (GTK_OBJECT (window), window_signals[SET_FOCUS], focus);
899 }
900
901 /**
902  * gtk_window_set_default:
903  * @window: a #GtkWindow
904  * @default_widget: widget to be the default
905  *
906  * The default widget is the widget that's activated when the user
907  * presses Enter in a dialog (for example). This function tells a
908  * #GtkWindow about the current default widget; it's really a GTK
909  * internal function and you shouldn't need it. Instead, to change the
910  * default widget, first set the #GTK_CAN_DEFAULT flag on the widget
911  * you'd like to make the default using GTK_WIDGET_SET_FLAGS(), then
912  * call gtk_widget_grab_default() to move the default.
913  * 
914  **/
915 void
916 gtk_window_set_default (GtkWindow *window,
917                         GtkWidget *default_widget)
918 {
919   g_return_if_fail (window != NULL);
920   g_return_if_fail (GTK_IS_WINDOW (window));
921
922   if (default_widget)
923     g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
924
925   if (window->default_widget != default_widget)
926     {
927       if (window->default_widget)
928         {
929           if (window->focus_widget != window->default_widget ||
930               !GTK_WIDGET_RECEIVES_DEFAULT (window->default_widget))
931             GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
932           gtk_widget_queue_draw (window->default_widget);
933         }
934
935       window->default_widget = default_widget;
936
937       if (window->default_widget)
938         {
939           if (window->focus_widget == NULL ||
940               !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))
941             GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
942           gtk_widget_queue_draw (window->default_widget);
943         }
944     }
945 }
946
947 void
948 gtk_window_set_policy (GtkWindow *window,
949                        gboolean   allow_shrink,
950                        gboolean   allow_grow,
951                        gboolean   auto_shrink)
952 {
953   g_return_if_fail (window != NULL);
954   g_return_if_fail (GTK_IS_WINDOW (window));
955
956   window->allow_shrink = (allow_shrink != FALSE);
957   window->allow_grow = (allow_grow != FALSE);
958   window->auto_shrink = (auto_shrink != FALSE);
959
960   g_object_notify (G_OBJECT (window), "allow_shrink");
961   g_object_notify (G_OBJECT (window), "allow_grow");
962   g_object_notify (G_OBJECT (window), "resizable");
963   g_object_notify (G_OBJECT (window), "auto_shrink");
964   
965   gtk_widget_queue_resize (GTK_WIDGET (window));
966 }
967
968 void
969 gtk_window_add_accel_group (GtkWindow        *window,
970                             GtkAccelGroup    *accel_group)
971 {
972   g_return_if_fail (window != NULL);
973   g_return_if_fail (GTK_IS_WINDOW (window));
974   g_return_if_fail (accel_group != NULL);
975
976   gtk_accel_group_attach (accel_group, GTK_OBJECT (window));
977 }
978
979 void
980 gtk_window_remove_accel_group (GtkWindow       *window,
981                                GtkAccelGroup   *accel_group)
982 {
983   g_return_if_fail (window != NULL);
984   g_return_if_fail (GTK_IS_WINDOW (window));
985   g_return_if_fail (accel_group != NULL);
986
987   gtk_accel_group_detach (accel_group, GTK_OBJECT (window));
988 }
989
990 void
991 gtk_window_add_mnemonic (GtkWindow *window,
992                          guint      keyval,
993                          GtkWidget *target)
994 {
995   GtkWindowMnemonic key;
996   GtkWindowMnemonic *mnemonic;
997
998   g_return_if_fail (GTK_IS_WINDOW (window));
999   g_return_if_fail (GTK_IS_WIDGET (target));
1000   
1001   key.window = window;
1002   key.keyval = keyval;
1003   mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1004
1005   if (mnemonic)
1006     {
1007       g_return_if_fail (g_slist_find (mnemonic->targets, target) == NULL);
1008       mnemonic->targets = g_slist_prepend (mnemonic->targets, target);
1009     }
1010   else
1011     {
1012       mnemonic = g_new (GtkWindowMnemonic, 1);
1013       *mnemonic = key;
1014       mnemonic->targets = g_slist_prepend (NULL, target);
1015       g_hash_table_insert (mnemonic_hash_table, mnemonic, mnemonic);
1016     }
1017 }
1018
1019 void
1020 gtk_window_remove_mnemonic (GtkWindow *window,
1021                             guint      keyval,
1022                             GtkWidget *target)
1023 {
1024   GtkWindowMnemonic key;
1025   GtkWindowMnemonic *mnemonic;
1026
1027   g_return_if_fail (GTK_IS_WINDOW (window));
1028   g_return_if_fail (GTK_IS_WIDGET (target));
1029   
1030   key.window = window;
1031   key.keyval = keyval;
1032   mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1033
1034   g_return_if_fail (mnemonic && g_slist_find (mnemonic->targets, target) != NULL);
1035
1036   mnemonic->targets = g_slist_remove (mnemonic->targets, target);
1037   if (mnemonic->targets == NULL)
1038     {
1039       g_hash_table_remove (mnemonic_hash_table, mnemonic);
1040       g_free (mnemonic);
1041     }
1042 }
1043
1044 gboolean
1045 gtk_window_mnemonic_activate (GtkWindow      *window,
1046                               guint           keyval,
1047                               GdkModifierType modifier)
1048 {
1049   GtkWindowMnemonic key;
1050   GtkWindowMnemonic *mnemonic;
1051   GSList *list;
1052   GtkWidget *widget, *chosen_widget;
1053   gboolean overloaded;
1054
1055   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1056
1057   if (window->mnemonic_modifier != (modifier & gtk_accelerator_get_default_mod_mask ()))
1058     return FALSE;
1059   
1060   key.window = window;
1061   key.keyval = keyval;
1062   mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1063
1064   if (!mnemonic)
1065     return FALSE;
1066   
1067   overloaded = FALSE;
1068   chosen_widget = NULL;
1069   list = mnemonic->targets;
1070   while (list)
1071     {
1072       widget = GTK_WIDGET (list->data);
1073       
1074       if (GTK_WIDGET_IS_SENSITIVE (widget) &&
1075           GTK_WIDGET_MAPPED (widget))
1076         {
1077           if (chosen_widget)
1078             {
1079               overloaded = TRUE;
1080               break;
1081             }
1082           else
1083             chosen_widget = widget;
1084         }
1085       list = g_slist_next (list);
1086     }
1087
1088   if (chosen_widget)
1089     {
1090       /* For round robin we put the activated entry on
1091        * the end of the list after activation
1092        */
1093       mnemonic->targets = g_slist_remove (mnemonic->targets, chosen_widget);
1094       mnemonic->targets = g_slist_append (mnemonic->targets, chosen_widget);
1095
1096       return gtk_widget_mnemonic_activate (chosen_widget, overloaded);
1097     }
1098   return FALSE;
1099 }
1100
1101 void
1102 gtk_window_set_mnemonic_modifier (GtkWindow      *window,
1103                                   GdkModifierType modifier)
1104 {
1105   g_return_if_fail (GTK_IS_WINDOW (window));
1106   g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
1107
1108   window->mnemonic_modifier = modifier;
1109 }
1110
1111 /**
1112  * gtk_window_get_mnemonic_modifier:
1113  * @window: a #GtkWindow
1114  *
1115  * Returns the mnemonic modifier for this window. See
1116  * gtk_window_set_mnemonic_modifier().
1117  *
1118  * Return value: the modifier mask used to activate
1119  *               mnemonics on this window.
1120  **/
1121 GdkModifierType
1122 gtk_window_get_mnemonic_modifier (GtkWindow *window)
1123 {
1124   g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
1125
1126   return window->mnemonic_modifier;
1127 }
1128
1129 void
1130 gtk_window_set_position (GtkWindow         *window,
1131                          GtkWindowPosition  position)
1132 {
1133   g_return_if_fail (GTK_IS_WINDOW (window));
1134
1135   window->position = position;
1136
1137   g_object_notify (G_OBJECT (window), "window_position");
1138 }
1139
1140 gboolean 
1141 gtk_window_activate_focus (GtkWindow *window)
1142 {
1143   g_return_val_if_fail (window != NULL, FALSE);
1144   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1145
1146   if (window->focus_widget)
1147     {
1148       if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1149         gtk_widget_activate (window->focus_widget);
1150       return TRUE;
1151     }
1152
1153   return FALSE;
1154 }
1155
1156 gboolean
1157 gtk_window_activate_default (GtkWindow *window)
1158 {
1159   g_return_val_if_fail (window != NULL, FALSE);
1160   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1161
1162   if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
1163       (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1164     {
1165       gtk_widget_activate (window->default_widget);
1166       return TRUE;
1167     }
1168   else if (window->focus_widget)
1169     {
1170       if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1171         gtk_widget_activate (window->focus_widget);
1172       return TRUE;
1173     }
1174
1175   return FALSE;
1176 }
1177
1178 /**
1179  * gtk_window_set_modal:
1180  * @window: a #GtkWindow
1181  * @modal: whether the window is modal
1182  * 
1183  * Sets a window modal or non-modal. Modal windows prevent interaction
1184  * with other windows in the same application. To keep modal dialogs
1185  * on top of main application windows, use
1186  * gtk_window_set_transient_for() to make the dialog transient for the
1187  * parent; most window managers will then disallow lowering the dialog
1188  * below the parent.
1189  * 
1190  * 
1191  **/
1192 void
1193 gtk_window_set_modal (GtkWindow *window,
1194                       gboolean   modal)
1195 {
1196   g_return_if_fail (window != NULL);
1197   g_return_if_fail (GTK_IS_WINDOW (window));
1198
1199   window->modal = modal != FALSE;
1200   
1201   /* adjust desired modality state */
1202   if (GTK_WIDGET_VISIBLE (window) && window->modal)
1203     gtk_grab_add (GTK_WIDGET (window));
1204   else
1205     gtk_grab_remove (GTK_WIDGET (window));
1206
1207   g_object_notify (G_OBJECT (window), "modal");
1208 }
1209
1210 /**
1211  * gtk_window_get_modal:
1212  * @window: a #GtkWindow
1213  * 
1214  * Returns whether the window is modal. See gtk_window_set_modal().
1215  *
1216  * Return value: %TRUE if the window is set to be modal and
1217  *               establishes a grab when shown
1218  **/
1219 gboolean
1220 gtk_window_get_modal (GtkWindow *window)
1221 {
1222   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1223
1224   return window->modal;
1225 }
1226
1227 /**
1228  * gtk_window_list_toplevels:
1229  * 
1230  * Returns a list of all existing toplevel windows. The widgets
1231  * in the list are not individually referenced. If you want
1232  * to iterate through the list and perform actions involving
1233  * callbacks that might destroy the widgets, you MUST call
1234  * g_list_foreach (result, (GFunc)g_object_ref, NULL) first, and
1235  * then unref all the widgets afterwards.
1236  * 
1237  * Return value: list of toplevel widgets
1238  **/
1239 GList*
1240 gtk_window_list_toplevels (void)
1241 {
1242   GList *list = NULL;
1243   GSList *slist;
1244
1245   for (slist = toplevel_list; slist; slist = slist->next)
1246     list = g_list_prepend (list, slist->data);
1247
1248   return list;
1249 }
1250
1251 void
1252 gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
1253 {
1254   GList *embedded_windows;
1255
1256   g_return_if_fail (window != NULL);
1257   g_return_if_fail (GTK_IS_WINDOW (window));
1258
1259   embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
1260   if (embedded_windows)
1261     gtk_object_remove_no_notify_by_id (GTK_OBJECT (window), 
1262                                        g_quark_from_static_string ("gtk-embedded"));
1263   embedded_windows = g_list_prepend (embedded_windows,
1264                                      GUINT_TO_POINTER (xid));
1265
1266   gtk_object_set_data_full (GTK_OBJECT (window), "gtk-embedded", 
1267                             embedded_windows,
1268                             embedded_windows ?
1269                               (GtkDestroyNotify) g_list_free : NULL);
1270 }
1271
1272 void
1273 gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
1274 {
1275   GList *embedded_windows;
1276   GList *node;
1277
1278   g_return_if_fail (window != NULL);
1279   g_return_if_fail (GTK_IS_WINDOW (window));
1280   
1281   embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
1282   if (embedded_windows)
1283     gtk_object_remove_no_notify_by_id (GTK_OBJECT (window), 
1284                                        g_quark_from_static_string ("gtk-embedded"));
1285
1286   node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
1287   if (node)
1288     {
1289       embedded_windows = g_list_remove_link (embedded_windows, node);
1290       g_list_free_1 (node);
1291     }
1292   
1293   gtk_object_set_data_full (GTK_OBJECT (window), 
1294                             "gtk-embedded", embedded_windows,
1295                             embedded_windows ?
1296                               (GtkDestroyNotify) g_list_free : NULL);
1297 }
1298
1299 void       
1300 _gtk_window_reposition (GtkWindow *window,
1301                         gint       x,
1302                         gint       y)
1303 {
1304   GtkWindowGeometryInfo *info;
1305   
1306   g_return_if_fail (window != NULL);
1307   g_return_if_fail (GTK_IS_WINDOW (window));
1308
1309   /* keep this in sync with gtk_window_compute_reposition()
1310    */
1311   if (GTK_WIDGET_REALIZED (window))
1312     {
1313       info = gtk_window_get_geometry_info (window, TRUE);
1314
1315       if (!(info->last.flags & GDK_HINT_POS))
1316         {
1317           info->last.flags |= GDK_HINT_POS;
1318           gdk_window_set_geometry_hints (GTK_WIDGET (window)->window,
1319                                          &info->last.geometry,
1320                                          info->last.flags);
1321         }
1322
1323       if (window->frame)
1324         gdk_window_move (window->frame,  x - window->frame_left, y - window->frame_top);
1325       else
1326         gdk_window_move (GTK_WIDGET (window)->window, x, y);
1327     }
1328 }
1329
1330 static void
1331 gtk_window_dispose (GObject *object)
1332 {
1333   GtkWindow *window;
1334
1335   g_return_if_fail (GTK_IS_WINDOW (object));
1336
1337   window = GTK_WINDOW (object);
1338
1339   gtk_window_set_focus (window, NULL);
1340   gtk_window_set_default (window, NULL);
1341
1342   G_OBJECT_CLASS (parent_class)->dispose (object);
1343 }
1344
1345 static void
1346 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
1347 {
1348   gtk_widget_destroy (GTK_WIDGET (child));
1349 }
1350
1351 static void
1352 connect_parent_destroyed (GtkWindow *window)
1353 {
1354   if (window->transient_parent)
1355     {
1356       gtk_signal_connect (GTK_OBJECT (window->transient_parent),
1357                           "destroy",
1358                           GTK_SIGNAL_FUNC (parent_destroyed_callback),
1359                           window);
1360     }  
1361 }
1362
1363 static void
1364 disconnect_parent_destroyed (GtkWindow *window)
1365 {
1366   if (window->transient_parent)
1367     {
1368       gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1369                                      GTK_SIGNAL_FUNC (parent_destroyed_callback),
1370                                      window);
1371     }
1372 }
1373
1374 static void
1375 gtk_window_transient_parent_realized (GtkWidget *parent,
1376                                       GtkWidget *window)
1377 {
1378   if (GTK_WIDGET_REALIZED (window))
1379     gdk_window_set_transient_for (window->window, parent->window);
1380 }
1381
1382 static void
1383 gtk_window_transient_parent_unrealized (GtkWidget *parent,
1384                                         GtkWidget *window)
1385 {
1386   if (GTK_WIDGET_REALIZED (window))
1387     gdk_property_delete (window->window, 
1388                          gdk_atom_intern ("WM_TRANSIENT_FOR", FALSE));
1389 }
1390
1391 static void       
1392 gtk_window_unset_transient_for  (GtkWindow *window)
1393 {
1394   if (window->transient_parent)
1395     {
1396       gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1397                                      GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
1398                                      window);
1399       gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1400                                      GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
1401                                      window);
1402       gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
1403                                      GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1404                                      &window->transient_parent);
1405
1406       if (window->destroy_with_parent)
1407         disconnect_parent_destroyed (window);
1408       
1409       window->transient_parent = NULL;
1410     }
1411 }
1412
1413 /**
1414  * gtk_window_set_transient_for:
1415  * @window: a #GtkWindow
1416  * @parent: parent window
1417  *
1418  * Dialog windows should be set transient for the main application
1419  * window they were spawned from. This allows window managers to
1420  * e.g. keep the dialog on top of the main window, or center the
1421  * dialog over the main window. gtk_dialog_new_with_buttons() and
1422  * other convenience functions in GTK+ will sometimes call
1423  * gtk_window_set_transient_for() on your behalf.
1424  * 
1425  **/
1426 void       
1427 gtk_window_set_transient_for  (GtkWindow *window, 
1428                                GtkWindow *parent)
1429 {
1430   g_return_if_fail (GTK_IS_WINDOW (window));
1431   g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
1432   g_return_if_fail (window != parent);
1433
1434     
1435   if (window->transient_parent)
1436     {
1437       if (GTK_WIDGET_REALIZED (window) && 
1438           GTK_WIDGET_REALIZED (window->transient_parent) && 
1439           (!parent || !GTK_WIDGET_REALIZED (parent)))
1440         gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
1441                                                 GTK_WIDGET (window));
1442
1443       gtk_window_unset_transient_for (window);
1444     }
1445
1446   window->transient_parent = parent;
1447
1448   if (parent)
1449     {
1450       gtk_signal_connect (GTK_OBJECT (parent), "destroy",
1451                           GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1452                           &window->transient_parent);
1453       gtk_signal_connect (GTK_OBJECT (parent), "realize",
1454                           GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
1455                           window);
1456       gtk_signal_connect (GTK_OBJECT (parent), "unrealize",
1457                           GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
1458                           window);
1459
1460       if (window->destroy_with_parent)
1461         connect_parent_destroyed (window);
1462       
1463       if (GTK_WIDGET_REALIZED (window) &&
1464           GTK_WIDGET_REALIZED (parent))
1465         gtk_window_transient_parent_realized (GTK_WIDGET (parent),
1466                                               GTK_WIDGET (window));
1467     }
1468 }
1469
1470 /**
1471  * gtk_window_get_transient_for:
1472  * @window: a #GtkWindow
1473  *
1474  * Fetches the transient parent for this window. See
1475  * gtk_window_set_transient_for().
1476  *
1477  * Return value: the transient parent for this window, or %NULL
1478  *    if no transient parent has been set.
1479  **/
1480 GtkWindow *
1481 gtk_window_get_transient_for (GtkWindow *window)
1482 {
1483   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1484
1485   return window->transient_parent;
1486 }
1487
1488 /**
1489  * gtk_window_set_type_hint:
1490  * @window: a #GtkWindow
1491  * @hint: the window type
1492  *
1493  * By setting the type hint for the window, you allow the window
1494  * manager to decorate and handle the window in a way which is
1495  * suitable to the function of the window in your application.
1496  *
1497  * This function should be called before the window becomes visible.
1498  *
1499  * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
1500  * will sometimes call gtk_window_set_type_hint() on your behalf.
1501  * 
1502  **/
1503 void
1504 gtk_window_set_type_hint (GtkWindow           *window, 
1505                           GdkWindowTypeHint    hint)
1506 {
1507   g_return_if_fail (GTK_IS_WINDOW (window));
1508   g_return_if_fail (!GTK_WIDGET_VISIBLE (window));
1509   window->type_hint = hint;
1510 }
1511
1512 /**
1513  * gtk_window_get_type_hint:
1514  * @window: a #GtkWindow
1515  *
1516  * Gets the type hint for this window. See gtk_window_set_type_hint().
1517  *
1518  * Return value: the type hint for @window.
1519  **/
1520 GdkWindowTypeHint
1521 gtk_window_get_type_hint (GtkWindow *window)
1522 {
1523   g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
1524
1525   return window->type_hint;
1526 }
1527
1528 /**
1529  * gtk_window_set_destroy_with_parent:
1530  * @window: a #GtkWindow
1531  * @setting: whether to destroy @window with its transient parent
1532  * 
1533  * If @setting is TRUE, then destroying the transient parent of @window
1534  * will also destroy @window itself. This is useful for dialogs that
1535  * shouldn't persist beyond the lifetime of the main window they're
1536  * associated with, for example.
1537  **/
1538 void
1539 gtk_window_set_destroy_with_parent  (GtkWindow *window,
1540                                      gboolean   setting)
1541 {
1542   g_return_if_fail (GTK_IS_WINDOW (window));
1543
1544   if (window->destroy_with_parent == (setting != FALSE))
1545     return;
1546
1547   if (window->destroy_with_parent)
1548     {
1549       disconnect_parent_destroyed (window);
1550     }
1551   else
1552     {
1553       connect_parent_destroyed (window);
1554     }
1555   
1556   window->destroy_with_parent = setting;
1557
1558   g_object_notify (G_OBJECT (window), "destroy_with_parent");
1559 }
1560
1561 /**
1562  * gtk_window_get_destroy_with_parent:
1563  * @window: a #GtkWindow
1564  * 
1565  * Returns whether the window will be destroyed with its transient parent. See
1566  * gtk_window_set_destroy_with_parent ().
1567  *
1568  * Return value: %TRUE if the window will be destroyed with its transient parent.
1569  **/
1570 gboolean
1571 gtk_window_get_destroy_with_parent (GtkWindow *window)
1572 {
1573   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1574
1575   return window->destroy_with_parent;
1576 }
1577
1578 static GtkWindowGeometryInfo*
1579 gtk_window_get_geometry_info (GtkWindow *window,
1580                               gboolean   create)
1581 {
1582   GtkWindowGeometryInfo *info;
1583
1584   info = window->geometry_info;
1585   if (!info && create)
1586     {
1587       info = g_new0 (GtkWindowGeometryInfo, 1);
1588
1589       info->width = 0;
1590       info->height = 0;
1591       info->last.width = -1;
1592       info->last.height = -1;
1593       info->widget = NULL;
1594       info->mask = 0;
1595       info->may_shrink = FALSE;
1596       window->geometry_info = info;
1597     }
1598
1599   return info;
1600 }
1601
1602 /**
1603  * gtk_window_set_geometry_hints:
1604  * @window: a #GtkWindow
1605  * @geometry_widget: widget the geometry hints will be applied to
1606  * @geometry: struct containing geometry information
1607  * @geom_mask: mask indicating which struct fields should be paid attention to
1608  *
1609  * This function sets up hints about how a window can be resized by
1610  * the user.  You can set a minimum and maximum size; allowed resize
1611  * increments (e.g. for xterm, you can only resize by the size of a
1612  * character); aspect ratios; and more. See the #GdkGeometry struct.
1613  * 
1614  **/
1615 void       
1616 gtk_window_set_geometry_hints (GtkWindow       *window,
1617                                GtkWidget       *geometry_widget,
1618                                GdkGeometry     *geometry,
1619                                GdkWindowHints   geom_mask)
1620 {
1621   GtkWindowGeometryInfo *info;
1622
1623   g_return_if_fail (window != NULL);
1624
1625   info = gtk_window_get_geometry_info (window, TRUE);
1626   
1627   if (info->widget)
1628     gtk_signal_disconnect_by_func (GTK_OBJECT (info->widget),
1629                                    GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1630                                    &info->widget);
1631   
1632   info->widget = geometry_widget;
1633   if (info->widget)
1634     gtk_signal_connect (GTK_OBJECT (geometry_widget), "destroy",
1635                         GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1636                         &info->widget);
1637
1638   if (geometry)
1639     info->geometry = *geometry;
1640
1641   info->mask = geom_mask;
1642
1643   gtk_widget_queue_resize (GTK_WIDGET (window));
1644 }
1645
1646 /**
1647  * gtk_window_set_decorated:
1648  * @window: a #GtkWindow
1649  * @setting: %TRUE to decorate the window
1650  *
1651  * By default, windows are decorated with a title bar, resize
1652  * controls, etc.  Some window managers allow GTK+ to disable these
1653  * decorations, creating a borderless window. If you set the decorated
1654  * property to %FALSE using this function, GTK+ will do its best to
1655  * convince the window manager not to decorate the window.
1656  * 
1657  **/
1658 void
1659 gtk_window_set_decorated (GtkWindow *window,
1660                           gboolean   setting)
1661 {
1662   g_return_if_fail (GTK_IS_WINDOW (window));
1663
1664   setting = setting != FALSE;
1665
1666   if (setting == window->decorated)
1667     return;
1668
1669   if (GTK_WIDGET (window)->window)
1670     {
1671       if (window->decorated)
1672         gdk_window_set_decorations (GTK_WIDGET (window)->window,
1673                                     GDK_DECOR_ALL);
1674       else
1675         gdk_window_set_decorations (GTK_WIDGET (window)->window,
1676                                     0);
1677     }
1678 }
1679
1680 /**
1681  * gtk_window_get_decorated:
1682  * @window: a #GtkWindow
1683  *
1684  * Returns whether the window has been set to have decorations
1685  * such as a title bar via gtk_window_set_decorated().
1686  *
1687  * Return value: %TRUE if the window has been set to have decorations
1688  **/
1689 gboolean
1690 gtk_window_get_decorated (GtkWindow *window)
1691 {
1692   g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
1693
1694   return window->decorated;
1695 }
1696
1697 /**
1698  * gtk_window_set_default_size:
1699  * @window: a #GtkWindow
1700  * @width: width in pixels, 0 to unset, or -1 to leave the width unchanged
1701  * @height: height in pixels, 0 to unset, or -1 to leave the height unchanged
1702  *
1703  * Sets the default size of a window. If the window's "natural" size
1704  * (its size request) is larger than the default, the default will be
1705  * ignored. So the default size is a minimum initial size.  Unlike
1706  * gtk_widget_set_usize(), which sets a size request for a widget and
1707  * thus would keep users from shrinking the window, this function only
1708  * sets the initial size, just as if the user had resized the window
1709  * themselves. Users can still shrink the window again as they
1710  * normally would. Setting a default size of 0 means to use the
1711  * "natural" default size (the size request of the window).
1712  *
1713  * For more control over a window's initial size and how resizing works,
1714  * investigate gtk_window_set_geometry_hints().
1715  *
1716  * A useful feature: if you set the "geometry widget" via
1717  * gtk_window_set_geometry_hints(), the default size specified by
1718  * gtk_window_set_default_size() will be the default size of that
1719  * widget, not of the entire window.
1720  * 
1721  **/
1722 void       
1723 gtk_window_set_default_size (GtkWindow   *window,
1724                              gint         width,
1725                              gint         height)
1726 {
1727   GtkWindowGeometryInfo *info;
1728
1729   g_return_if_fail (GTK_IS_WINDOW (window));
1730
1731   info = gtk_window_get_geometry_info (window, TRUE);
1732
1733   g_object_freeze_notify (G_OBJECT (window));
1734   if (width >= 0)
1735     {
1736       info->width = width;
1737       g_object_notify (G_OBJECT (window), "default_width");
1738       info->may_shrink = TRUE;
1739     }
1740   if (height >= 0)
1741     {
1742       info->height = height;
1743       g_object_notify (G_OBJECT (window), "default_height");
1744       info->may_shrink = TRUE;
1745     }
1746   g_object_thaw_notify (G_OBJECT (window));
1747   
1748   gtk_widget_queue_resize (GTK_WIDGET (window));
1749 }
1750
1751 /**
1752  * gtk_window_get_default_size:
1753  * @window: a #GtkWindow
1754  * @width: location to store the default width, or %NULL
1755  * @height: location to store the default height, or %NULL
1756  *
1757  * Gets the default size of the window. A value of 0 for the
1758  * width or height indicates that a default size has not
1759  * been explicitely set for that dimension, so the value
1760  * will be computed from the requisition of the window.
1761  **/
1762 void
1763 gtk_window_get_default_size (GtkWindow *window,
1764                              gint      *width,
1765                              gint      *height)
1766 {
1767   GtkWindowGeometryInfo *info;
1768
1769   g_return_if_fail (GTK_IS_WINDOW (window));
1770
1771   info = gtk_window_get_geometry_info (window, FALSE);
1772
1773   if (width)
1774     *width = info ? info->width : 0;
1775
1776   if (height)
1777     *height = info ? info->height : 0;
1778 }
1779   
1780 static void
1781 gtk_window_destroy (GtkObject *object)
1782 {
1783   GtkWindow *window;
1784   
1785   g_return_if_fail (GTK_IS_WINDOW (object));
1786
1787   window = GTK_WINDOW (object);
1788
1789   if (window->transient_parent)
1790     gtk_window_set_transient_for (window, NULL);
1791
1792   if (window->has_user_ref_count)
1793     {
1794       window->has_user_ref_count = FALSE;
1795       gtk_widget_unref (GTK_WIDGET (window));
1796     }
1797
1798   if (window->group)
1799     gtk_window_group_remove_window (window->group, window);
1800
1801   GTK_OBJECT_CLASS (parent_class)->destroy (object);
1802 }
1803
1804 static gboolean
1805 gtk_window_mnemonic_hash_remove (gpointer       key,
1806                                  gpointer       value,
1807                                  gpointer       user)
1808 {
1809   GtkWindowMnemonic *mnemonic = key;
1810   GtkWindow *window = user;
1811
1812   if (mnemonic->window == window)
1813     {
1814       if (mnemonic->targets)
1815         {
1816           gchar *name = gtk_accelerator_name (mnemonic->keyval, 0);
1817
1818           g_warning ("mnemonic \"%s\" wasn't removed for widget (%p)",
1819                      name, mnemonic->targets->data);
1820           g_free (name);
1821         }
1822       g_slist_free (mnemonic->targets);
1823       g_free (mnemonic);
1824       
1825       return TRUE;
1826     }
1827   return FALSE;
1828 }
1829
1830 static void
1831 gtk_window_finalize (GObject *object)
1832 {
1833   GtkWindow *window;
1834
1835   g_return_if_fail (GTK_IS_WINDOW (object));
1836
1837   window = GTK_WINDOW (object);
1838
1839   toplevel_list = g_slist_remove (toplevel_list, window);
1840
1841   g_free (window->title);
1842   g_free (window->wmclass_name);
1843   g_free (window->wmclass_class);
1844   g_free (window->wm_role);
1845
1846   g_hash_table_foreach_remove (mnemonic_hash_table,
1847                                gtk_window_mnemonic_hash_remove,
1848                                window);
1849   if (window->geometry_info)
1850     {
1851       if (window->geometry_info->widget)
1852         gtk_signal_disconnect_by_func (GTK_OBJECT (window->geometry_info->widget),
1853                                        GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1854                                        &window->geometry_info->widget);
1855       g_free (window->geometry_info);
1856     }
1857   
1858   G_OBJECT_CLASS (parent_class)->finalize (object);
1859 }
1860
1861 static void
1862 gtk_window_show (GtkWidget *widget)
1863 {
1864   GtkWindow *window = GTK_WINDOW (widget);
1865   GtkContainer *container = GTK_CONTAINER (window);
1866   gboolean need_resize;
1867   
1868   GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
1869   
1870   need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
1871   container->need_resize = FALSE;
1872   
1873   if (need_resize)
1874     {
1875       GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
1876       GtkAllocation allocation = { 0, 0 };
1877       GdkGeometry new_geometry;
1878       guint width, height, new_flags;
1879       gboolean was_realized;
1880       
1881       /* determine default size to initially show the window with */
1882       gtk_widget_size_request (widget, NULL);
1883       gtk_window_compute_default_size (window, &width, &height);
1884       
1885       /* save away the last default size for later comparisions */
1886       info->last.width = width;
1887       info->last.height = height;
1888
1889       /* constrain size to geometry */
1890       gtk_window_compute_hints (window, &new_geometry, &new_flags);
1891       gtk_window_constrain_size (window,
1892                                  &new_geometry, new_flags,
1893                                  width, height,
1894                                  &width, &height);
1895       
1896       /* and allocate the window */
1897       allocation.width  = width;
1898       allocation.height = height;
1899       gtk_widget_size_allocate (widget, &allocation);
1900       
1901       was_realized = FALSE;
1902       if (!GTK_WIDGET_REALIZED (widget))
1903         {
1904           gtk_widget_realize (widget);
1905           was_realized = TRUE;;
1906         }
1907
1908       /* Must be done after the windows are realized,
1909        * so that the decorations can be read
1910        */
1911       gtk_decorated_window_calculate_frame_size (window);
1912       
1913       if (!was_realized)
1914         gdk_window_resize (widget->window, width, height);
1915     }
1916   
1917   gtk_container_check_resize (container);
1918
1919   gtk_widget_map (widget);
1920
1921   if (window->modal)
1922     gtk_grab_add (widget);
1923 }
1924
1925 static void
1926 gtk_window_hide (GtkWidget *widget)
1927 {
1928   GtkWindow *window;
1929
1930   g_return_if_fail (widget != NULL);
1931   g_return_if_fail (GTK_IS_WINDOW (widget));
1932
1933   window = GTK_WINDOW (widget);
1934
1935   GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
1936   gtk_widget_unmap (widget);
1937
1938   if (window->modal)
1939     gtk_grab_remove (widget);
1940 }
1941
1942 static void
1943 gtk_window_map (GtkWidget *widget)
1944 {
1945   GtkWindow *window;
1946   GdkWindow *toplevel;
1947   
1948   g_return_if_fail (widget != NULL);
1949   g_return_if_fail (GTK_IS_WINDOW (widget));
1950
1951   GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
1952
1953   window = GTK_WINDOW (widget);
1954
1955   if (window->bin.child &&
1956       GTK_WIDGET_VISIBLE (window->bin.child) &&
1957       !GTK_WIDGET_MAPPED (window->bin.child))
1958     gtk_widget_map (window->bin.child);
1959
1960   if (window->frame)
1961     toplevel = window->frame;
1962   else
1963     toplevel = widget->window;
1964   
1965   if (window->maximize_initially)
1966     gdk_window_maximize (toplevel);
1967   else
1968     gdk_window_unmaximize (toplevel);
1969   
1970   if (window->stick_initially)
1971     gdk_window_stick (toplevel);
1972   else
1973     gdk_window_unstick (toplevel);
1974   
1975   if (window->iconify_initially)
1976     gdk_window_iconify (toplevel);
1977   else
1978     gdk_window_deiconify (toplevel);
1979   
1980   gdk_window_show (widget->window);
1981
1982   if (window->frame)
1983     gdk_window_show (window->frame);
1984 }
1985
1986 static void
1987 gtk_window_unmap (GtkWidget *widget)
1988 {
1989   GtkWindow *window;
1990
1991   g_return_if_fail (widget != NULL);
1992   g_return_if_fail (GTK_IS_WINDOW (widget));
1993
1994   window = GTK_WINDOW (widget);
1995   
1996   GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1997   if (window->frame)
1998     gdk_window_withdraw (window->frame);
1999   else 
2000     gdk_window_withdraw (widget->window);
2001
2002   window->use_uposition = TRUE;
2003   window->resize_count = 0;
2004   window->handling_resize = FALSE;
2005
2006 }
2007
2008 static void
2009 gtk_window_realize (GtkWidget *widget)
2010 {
2011   GtkWindow *window;
2012   GdkWindow *parent_window;
2013   GdkWindowAttr attributes;
2014   gint attributes_mask;
2015   
2016   g_return_if_fail (GTK_IS_WINDOW (widget));
2017
2018   window = GTK_WINDOW (widget);
2019
2020   /* ensure widget tree is properly size allocated */
2021   if (widget->allocation.x == -1 &&
2022       widget->allocation.y == -1 &&
2023       widget->allocation.width == 1 &&
2024       widget->allocation.height == 1)
2025     {
2026       GtkRequisition requisition;
2027       GtkAllocation allocation = { 0, 0, 200, 200 };
2028
2029       gtk_widget_size_request (widget, &requisition);
2030       if (requisition.width || requisition.height)
2031         {
2032           /* non-empty window */
2033           allocation.width = requisition.width;
2034           allocation.height = requisition.height;
2035         }
2036       gtk_widget_size_allocate (widget, &allocation);
2037       
2038       gtk_container_queue_resize (GTK_CONTAINER (widget));
2039
2040       g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
2041     }
2042   
2043   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
2044   
2045   switch (window->type)
2046     {
2047     case GTK_WINDOW_TOPLEVEL:
2048       attributes.window_type = GDK_WINDOW_TOPLEVEL;
2049       break;
2050     case GTK_WINDOW_POPUP:
2051       attributes.window_type = GDK_WINDOW_TEMP;
2052       break;
2053     default:
2054       g_warning (G_STRLOC": Unknown window type %d!", window->type);
2055       break;
2056     }
2057    
2058   attributes.title = window->title;
2059   attributes.wmclass_name = window->wmclass_name;
2060   attributes.wmclass_class = window->wmclass_class;
2061   attributes.wclass = GDK_INPUT_OUTPUT;
2062   attributes.visual = gtk_widget_get_visual (widget);
2063   attributes.colormap = gtk_widget_get_colormap (widget);
2064
2065   if (window->has_frame)
2066     {
2067       attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
2068       attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
2069       attributes.event_mask = (GDK_EXPOSURE_MASK |
2070                                GDK_KEY_PRESS_MASK |
2071                                GDK_ENTER_NOTIFY_MASK |
2072                                GDK_LEAVE_NOTIFY_MASK |
2073                                GDK_FOCUS_CHANGE_MASK |
2074                                GDK_STRUCTURE_MASK |
2075                                GDK_BUTTON_MOTION_MASK |
2076                                GDK_POINTER_MOTION_HINT_MASK |
2077                                GDK_BUTTON_PRESS_MASK |
2078                                GDK_BUTTON_RELEASE_MASK);
2079       
2080       attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
2081       
2082       window->frame = gdk_window_new (NULL, &attributes, attributes_mask);
2083       gdk_window_set_user_data (window->frame, widget);
2084       
2085       attributes.window_type = GDK_WINDOW_CHILD;
2086       attributes.x = window->frame_left;
2087       attributes.y = window->frame_right;
2088     
2089       attributes_mask = GDK_WA_X | GDK_WA_Y;
2090
2091       parent_window = window->frame;
2092     }
2093   else
2094     {
2095       attributes_mask = 0;
2096       parent_window = NULL;
2097     }
2098   
2099   attributes.width = widget->allocation.width;
2100   attributes.height = widget->allocation.height;
2101   attributes.event_mask = gtk_widget_get_events (widget);
2102   attributes.event_mask |= (GDK_EXPOSURE_MASK |
2103                             GDK_KEY_PRESS_MASK |
2104                             GDK_ENTER_NOTIFY_MASK |
2105                             GDK_LEAVE_NOTIFY_MASK |
2106                             GDK_FOCUS_CHANGE_MASK |
2107                             GDK_STRUCTURE_MASK);
2108
2109   attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
2110   attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
2111   attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
2112   widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
2113   gdk_window_set_user_data (widget->window, window);
2114       
2115   widget->style = gtk_style_attach (widget->style, widget->window);
2116   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
2117   if (window->frame)
2118     gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
2119
2120   /* This is a bad hack to set the window background. */
2121   gtk_window_paint (widget, NULL);
2122   
2123   if (window->transient_parent &&
2124       GTK_WIDGET_REALIZED (window->transient_parent))
2125     gdk_window_set_transient_for (widget->window,
2126                                   GTK_WIDGET (window->transient_parent)->window);
2127
2128   if (window->wm_role)
2129     gdk_window_set_role (widget->window, window->wm_role);
2130   
2131   if (!window->decorated)
2132     gdk_window_set_decorations (widget->window, 0);
2133
2134   gdk_window_set_type_hint (widget->window, window->type_hint);
2135
2136   /* transient_for must be set to allow the modal hint */
2137   if (window->transient_parent && window->modal)
2138     gdk_window_set_modal_hint (widget->window, TRUE);
2139   else
2140     gdk_window_set_modal_hint (widget->window, FALSE);
2141 }
2142
2143 static void
2144 gtk_window_unrealize (GtkWidget *widget)
2145 {
2146   GtkWindow *window;
2147
2148   g_return_if_fail (widget != NULL);
2149   g_return_if_fail (GTK_IS_WINDOW (widget));
2150
2151   window = GTK_WINDOW (widget);
2152
2153   if (window->frame)
2154     {
2155       gdk_window_set_user_data (window->frame, NULL);
2156       gdk_window_destroy (window->frame);
2157       window->frame = NULL;
2158     }
2159   
2160   (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
2161 }
2162
2163 static void
2164 gtk_window_size_request (GtkWidget      *widget,
2165                          GtkRequisition *requisition)
2166 {
2167   GtkWindow *window;
2168   GtkBin *bin;
2169
2170   g_return_if_fail (widget != NULL);
2171   g_return_if_fail (GTK_IS_WINDOW (widget));
2172   g_return_if_fail (requisition != NULL);
2173
2174   window = GTK_WINDOW (widget);
2175   bin = GTK_BIN (window);
2176   
2177   requisition->width = GTK_CONTAINER (window)->border_width * 2;
2178   requisition->height = GTK_CONTAINER (window)->border_width * 2;
2179
2180   if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
2181     {
2182       GtkRequisition child_requisition;
2183       
2184       gtk_widget_size_request (bin->child, &child_requisition);
2185
2186       requisition->width += child_requisition.width;
2187       requisition->height += child_requisition.height;
2188     }
2189 }
2190
2191 static void
2192 gtk_window_size_allocate (GtkWidget     *widget,
2193                           GtkAllocation *allocation)
2194 {
2195   GtkWindow *window;
2196   GtkAllocation child_allocation;
2197
2198   g_return_if_fail (widget != NULL);
2199   g_return_if_fail (GTK_IS_WINDOW (widget));
2200   g_return_if_fail (allocation != NULL);
2201
2202   window = GTK_WINDOW (widget);
2203   widget->allocation = *allocation;
2204
2205   if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
2206     {
2207       child_allocation.x = GTK_CONTAINER (window)->border_width;
2208       child_allocation.y = GTK_CONTAINER (window)->border_width;
2209       child_allocation.width =
2210         MAX (1, (gint)allocation->width - child_allocation.x * 2);
2211       child_allocation.height =
2212         MAX (1, (gint)allocation->height - child_allocation.y * 2);
2213
2214       gtk_widget_size_allocate (window->bin.child, &child_allocation);
2215     }
2216
2217   if (GTK_WIDGET_REALIZED (widget) && window->frame)
2218     {
2219       gdk_window_resize (window->frame,
2220                          allocation->width + window->frame_left + window->frame_right,
2221                          allocation->height + window->frame_top + window->frame_bottom);
2222     }
2223 }
2224
2225 static gint
2226 gtk_window_event (GtkWidget *widget, GdkEvent *event)
2227 {
2228   GtkWindow *window;
2229   gboolean return_val;
2230
2231   
2232   g_return_val_if_fail (widget != NULL, FALSE);
2233   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
2234   g_return_val_if_fail (event != NULL, FALSE);
2235   
2236   window = GTK_WINDOW (widget);
2237
2238   if (window->frame && (event->any.window == window->frame))
2239     {
2240       if ((event->type != GDK_KEY_PRESS) &&
2241           (event->type != GDK_KEY_RELEASE) &&
2242           (event->type != GDK_FOCUS_CHANGE))
2243         {
2244           gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "event");
2245           return_val = FALSE;
2246           gtk_signal_emit (GTK_OBJECT (widget), window_signals[FRAME_EVENT], event, &return_val);
2247           return TRUE;
2248         }
2249       else
2250         {
2251           g_object_unref (event->any.window);
2252           event->any.window = g_object_ref (widget->window);
2253         }
2254     }
2255
2256   return FALSE;
2257 }
2258
2259 static gboolean
2260 gtk_window_frame_event (GtkWidget *widget, GdkEvent *event)
2261 {
2262   GdkEventConfigure *configure_event;
2263   GtkWindow *window = GTK_WINDOW (widget);
2264   GdkRectangle rect;
2265
2266   switch (event->type)
2267     {
2268     case GDK_CONFIGURE:
2269       configure_event = (GdkEventConfigure *)event;
2270       
2271       /* Invalidate the decorations */
2272       rect.x = 0;
2273       rect.y = 0;
2274       rect.width = configure_event->width;
2275       rect.height = configure_event->height;
2276       
2277       gdk_window_invalidate_rect (window->frame, &rect, FALSE);
2278
2279       /* Pass on the (modified) configure event */
2280       configure_event->width -= window->frame_left + window->frame_right;
2281       configure_event->height -= window->frame_top + window->frame_bottom;
2282       return gtk_window_configure_event (widget, configure_event);
2283       break;
2284     default:
2285       break;
2286     }
2287   return FALSE;
2288 }
2289
2290 static gint
2291 gtk_window_configure_event (GtkWidget         *widget,
2292                             GdkEventConfigure *event)
2293 {
2294   GtkWindow *window;
2295   
2296   g_return_val_if_fail (widget != NULL, FALSE);
2297   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
2298   g_return_val_if_fail (event != NULL, FALSE);
2299   
2300   window = GTK_WINDOW (widget);
2301
2302   /* we got a configure event specifying the new window size and position,
2303    * in principle we have to distinguish 4 cases here:
2304    * 1) the size didn't change and resize_count == 0
2305    *    -> the window was merely moved (sometimes not even that)
2306    * 2) the size didn't change and resize_count > 0
2307    *    -> we requested a new size, but didn't get it
2308    * 3) the size changed and resize_count > 0
2309    *    -> we asked for a new size and we got one
2310    * 4) the size changed and resize_count == 0
2311    *    -> we got resized from outside the toolkit, and have to
2312    *    accept that size since we don't want to fight neither the
2313    *    window manager nor the user
2314    * in the three latter cases we have to reallocate the widget tree,
2315    * which happens in gtk_window_move_resize(), so we set a flag for
2316    * that function and assign the new size. if resize_count > 1,
2317    * we simply do nothing and wait for more configure events.
2318    */
2319
2320   if (window->resize_count > 0 ||
2321       widget->allocation.width != event->width ||
2322       widget->allocation.height != event->height)
2323     {
2324       if (window->resize_count > 0)
2325         window->resize_count -= 1;
2326
2327       if (window->resize_count == 0)
2328         {
2329           window->handling_resize = TRUE;
2330           
2331           widget->allocation.width = event->width;
2332           widget->allocation.height = event->height;
2333           
2334           gtk_widget_queue_resize (widget);
2335         }
2336     }
2337
2338   return TRUE;
2339 }
2340
2341 static gint
2342 gtk_window_key_press_event (GtkWidget   *widget,
2343                             GdkEventKey *event)
2344 {
2345   GtkWindow *window;
2346   gboolean handled;
2347
2348   g_return_val_if_fail (widget != NULL, FALSE);
2349   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
2350   g_return_val_if_fail (event != NULL, FALSE);
2351
2352   window = GTK_WINDOW (widget);
2353
2354   handled = FALSE;
2355   
2356   if (window->focus_widget && window->focus_widget != widget &&
2357       GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
2358     handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
2359
2360   if (!handled)
2361     handled = gtk_window_mnemonic_activate (window,
2362                                             event->keyval,
2363                                             event->state);
2364
2365   if (!handled)
2366     handled = gtk_accel_groups_activate (GTK_OBJECT (window), event->keyval, event->state);
2367
2368   /* Chain up, invokes binding set */
2369   if (!handled && GTK_WIDGET_CLASS (parent_class)->key_press_event)
2370     handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
2371
2372   return handled;
2373 }
2374
2375
2376 static void
2377 gtk_window_real_activate_default (GtkWindow *window)
2378 {
2379   gtk_window_activate_default (window);
2380 }
2381
2382 static void
2383 gtk_window_real_activate_focus (GtkWindow *window)
2384 {
2385   gtk_window_activate_focus (window);
2386 }
2387
2388 static void
2389 gtk_window_move_focus (GtkWindow       *window,
2390                        GtkDirectionType dir)
2391 {
2392   gtk_widget_child_focus (GTK_WIDGET (window), dir);
2393   
2394   if (!GTK_CONTAINER (window)->focus_child)
2395     gtk_window_set_focus (window, NULL);
2396 }
2397
2398 static gint
2399 gtk_window_key_release_event (GtkWidget   *widget,
2400                               GdkEventKey *event)
2401 {
2402   GtkWindow *window;
2403   gint handled;
2404   
2405   g_return_val_if_fail (widget != NULL, FALSE);
2406   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
2407   g_return_val_if_fail (event != NULL, FALSE);
2408   
2409   window = GTK_WINDOW (widget);
2410   handled = FALSE;
2411   if (window->focus_widget &&
2412       window->focus_widget != widget &&
2413       GTK_WIDGET_SENSITIVE (window->focus_widget))
2414     {
2415       handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
2416     }
2417
2418   if (!handled && GTK_WIDGET_CLASS (parent_class)->key_release_event)
2419     handled = GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
2420
2421   return handled;
2422 }
2423
2424 static gint
2425 gtk_window_enter_notify_event (GtkWidget        *widget,
2426                                GdkEventCrossing *event)
2427 {
2428   g_return_val_if_fail (widget != NULL, FALSE);
2429   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
2430   g_return_val_if_fail (event != NULL, FALSE);
2431
2432   return FALSE;
2433 }
2434
2435 static gint
2436 gtk_window_leave_notify_event (GtkWidget        *widget,
2437                                GdkEventCrossing *event)
2438 {
2439   g_return_val_if_fail (widget != NULL, FALSE);
2440   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
2441   g_return_val_if_fail (event != NULL, FALSE);
2442
2443   return FALSE;
2444 }
2445
2446 static gint
2447 gtk_window_focus_in_event (GtkWidget     *widget,
2448                            GdkEventFocus *event)
2449 {
2450   GtkWindow *window = GTK_WINDOW (widget);
2451   GdkEventFocus fevent;
2452
2453   /* It appears spurious focus in events can occur when
2454    *  the window is hidden. So we'll just check to see if
2455    *  the window is visible before actually handling the
2456    *  event
2457    */
2458   if (GTK_WIDGET_VISIBLE (widget))
2459     {
2460       window->has_focus = TRUE;
2461       
2462       if (window->focus_widget &&
2463           window->focus_widget != widget &&
2464           !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
2465         {
2466           fevent.type = GDK_FOCUS_CHANGE;
2467           fevent.window = window->focus_widget->window;
2468           fevent.in = TRUE;
2469
2470           gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
2471         }
2472     }
2473
2474   return FALSE;
2475 }
2476
2477 static gint
2478 gtk_window_focus_out_event (GtkWidget     *widget,
2479                             GdkEventFocus *event)
2480 {
2481   GtkWindow *window = GTK_WINDOW (widget);
2482   GdkEventFocus fevent;
2483
2484   window->has_focus = FALSE;
2485   
2486   if (window->focus_widget &&
2487       window->focus_widget != widget &&
2488       GTK_WIDGET_HAS_FOCUS (window->focus_widget))
2489     {
2490       fevent.type = GDK_FOCUS_CHANGE;
2491       fevent.window = window->focus_widget->window;
2492       fevent.in = FALSE;
2493
2494       gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
2495     }
2496
2497   return FALSE;
2498 }
2499
2500 static GdkAtom atom_rcfiles = GDK_NONE;
2501
2502 static void
2503 gtk_window_read_rcfiles (GtkWidget *widget,
2504                          GdkEventClient *event)
2505 {
2506   GList *embedded_windows;
2507
2508   embedded_windows = gtk_object_get_data (GTK_OBJECT (widget), "gtk-embedded");
2509   if (embedded_windows)
2510     {
2511       GdkEventClient sev;
2512       int i;
2513       
2514       for (i = 0; i < 5; i++)
2515         sev.data.l[i] = 0;
2516       sev.data_format = 32;
2517       sev.message_type = atom_rcfiles;
2518       
2519       while (embedded_windows)
2520         {
2521           guint xid = GPOINTER_TO_UINT (embedded_windows->data);
2522           gdk_event_send_client_message ((GdkEvent *) &sev, xid);
2523           embedded_windows = embedded_windows->next;
2524         }
2525     }
2526
2527   gtk_rc_reparse_all ();
2528 }
2529
2530 static gint
2531 gtk_window_client_event (GtkWidget      *widget,
2532                          GdkEventClient *event)
2533 {
2534   g_return_val_if_fail (widget != NULL, FALSE);
2535   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
2536   g_return_val_if_fail (event != NULL, FALSE);
2537
2538   if (!atom_rcfiles)
2539     atom_rcfiles = gdk_atom_intern ("_GTK_READ_RCFILES", FALSE);
2540
2541   if (event->message_type == atom_rcfiles) 
2542     gtk_window_read_rcfiles (widget, event);    
2543
2544   return FALSE;
2545 }
2546
2547 static void
2548 gtk_window_check_resize (GtkContainer *container)
2549 {
2550   GtkWindow *window;
2551
2552   g_return_if_fail (container != NULL);
2553   g_return_if_fail (GTK_IS_WINDOW (container));
2554
2555   window = GTK_WINDOW (container);
2556
2557   if (GTK_WIDGET_VISIBLE (container))
2558     gtk_window_move_resize (window);
2559 }
2560
2561 static gboolean
2562 gtk_window_focus (GtkWidget        *widget,
2563                   GtkDirectionType  direction)
2564 {
2565   GtkBin *bin;
2566   GtkWindow *window;
2567   GtkContainer *container;
2568   GtkWidget *old_focus_child;
2569   GtkWidget *parent;
2570
2571   container = GTK_CONTAINER (widget);
2572   window = GTK_WINDOW (widget);
2573   bin = GTK_BIN (widget);
2574
2575   old_focus_child = container->focus_child;
2576   
2577   /* We need a special implementation here to deal properly with wrapping
2578    * around in the tab chain without the danger of going into an
2579    * infinite loop.
2580    */
2581   if (old_focus_child)
2582     {
2583       if (gtk_widget_child_focus (old_focus_child, direction))
2584         return TRUE;
2585     }
2586
2587   if (window->focus_widget)
2588     {
2589       /* Wrapped off the end, clear the focus setting for the toplpevel */
2590       parent = window->focus_widget->parent;
2591       while (parent)
2592         {
2593           gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
2594           parent = GTK_WIDGET (parent)->parent;
2595         }
2596       
2597       gtk_window_set_focus (GTK_WINDOW (container), NULL);
2598     }
2599
2600   /* Now try to focus the first widget in the window */
2601   if (bin->child)
2602     {
2603       if (gtk_widget_child_focus (bin->child, direction))
2604         return TRUE;
2605     }
2606
2607   return FALSE;
2608 }
2609
2610 static void
2611 gtk_window_real_set_focus (GtkWindow *window,
2612                            GtkWidget *focus)
2613 {
2614   GdkEventFocus event;
2615   gboolean def_flags = 0;
2616
2617   g_return_if_fail (window != NULL);
2618   g_return_if_fail (GTK_IS_WINDOW (window));
2619   
2620   if (window->default_widget)
2621     def_flags = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
2622   
2623   if (window->focus_widget)
2624     {
2625       if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
2626           (window->focus_widget != window->default_widget))
2627         {
2628           GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
2629
2630           if (window->default_widget)
2631             GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
2632         }
2633
2634       if (window->has_focus)
2635         {
2636           event.type = GDK_FOCUS_CHANGE;
2637           event.window = window->focus_widget->window;
2638           event.in = FALSE;
2639           
2640           gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
2641         }
2642     }
2643   
2644   window->focus_widget = focus;
2645   
2646   if (window->focus_widget)
2647     {
2648       if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
2649           (window->focus_widget != window->default_widget))
2650         {
2651           if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
2652             GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
2653
2654           if (window->default_widget)
2655             GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
2656         }
2657
2658       if (window->has_focus)
2659         {
2660           event.type = GDK_FOCUS_CHANGE;
2661           event.window = window->focus_widget->window;
2662           event.in = TRUE;
2663           
2664           gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
2665         }
2666     }
2667   
2668   if (window->default_widget &&
2669       (def_flags != GTK_WIDGET_FLAGS (window->default_widget)))
2670     gtk_widget_queue_draw (window->default_widget);
2671 }
2672
2673
2674
2675 /*********************************
2676  * Functions related to resizing *
2677  *********************************/
2678
2679 static void
2680 gtk_window_move_resize (GtkWindow *window)
2681 {
2682   GtkWidget *widget;
2683   GtkContainer *container;
2684   GtkWindowGeometryInfo *info;
2685   GtkWindowLastGeometryInfo saved_last_info;
2686   GdkGeometry new_geometry;
2687   guint new_flags;
2688   gint x, y;
2689   gint width, height;
2690   gint new_width, new_height;
2691   gboolean need_reposition;
2692   gboolean default_size_changed = FALSE;
2693   gboolean hints_changed = FALSE;
2694   gboolean may_shrink = window->auto_shrink;
2695
2696   g_return_if_fail (GTK_WIDGET_REALIZED (window));
2697
2698   widget = GTK_WIDGET (window);
2699   container = GTK_CONTAINER (widget);
2700   info = gtk_window_get_geometry_info (window, TRUE);
2701   saved_last_info = info->last;
2702
2703   gtk_widget_size_request (widget, NULL);
2704   gtk_window_compute_default_size (window, &new_width, &new_height);
2705   
2706   if (info->last.width < 0 ||
2707       info->last.width != new_width ||
2708       info->last.height != new_height)
2709     {
2710       default_size_changed = TRUE;
2711       may_shrink |= info->may_shrink;
2712       info->last.width = new_width;
2713       info->last.height = new_height;
2714
2715       /* We need to force a reposition in this case
2716        */
2717       if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
2718         window->use_uposition = TRUE;
2719     }
2720   info->may_shrink = FALSE;
2721   
2722   /* Compute new set of hints for the window
2723    */
2724   gtk_window_compute_hints (window, &new_geometry, &new_flags);
2725   if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
2726                                  &new_geometry, new_flags))
2727     {
2728       hints_changed = TRUE;
2729       info->last.geometry = new_geometry;
2730       info->last.flags = new_flags;
2731     }
2732
2733   /* From the default size and the allocation, figure out the size
2734    * the window should be.
2735    */
2736   if (!default_size_changed ||
2737       (!may_shrink &&
2738        new_width <= widget->allocation.width &&
2739        new_height <= widget->allocation.height))
2740     {
2741       new_width = widget->allocation.width;
2742       new_height = widget->allocation.height;
2743     }
2744
2745   /* constrain the window size to the specified geometry */
2746   gtk_window_constrain_size (window,
2747                              &new_geometry, new_flags,
2748                              new_width, new_height,
2749                              &new_width, &new_height);
2750
2751   /* compute new window position if a move is required
2752    */
2753   need_reposition = gtk_window_compute_reposition (window, new_width, new_height, &x, &y);
2754   if (need_reposition && !(new_flags & GDK_HINT_POS))
2755     {
2756       new_flags |= GDK_HINT_POS;
2757       hints_changed = TRUE;
2758     }
2759
2760
2761   /* handle actual resizing:
2762    * - handle reallocations due to configure events
2763    * - figure whether we need to request a new window size
2764    * - handle simple resizes within our widget tree
2765    * - reposition window if neccessary
2766    */
2767   width = widget->allocation.width;
2768   height = widget->allocation.height;
2769
2770   if (window->handling_resize)
2771     { 
2772       GtkAllocation allocation;
2773       
2774       /* if we are just responding to a configure event, which
2775        * might be due to a resize by the window manager, the
2776        * user, or a response to a resizing request we made
2777        * earlier, we go ahead, allocate the new size and we're done
2778        * (see gtk_window_configure_event() for more details).
2779        */
2780       
2781       window->handling_resize = FALSE;
2782       
2783       allocation = widget->allocation;
2784       
2785       gtk_widget_size_allocate (widget, &allocation);
2786       gtk_widget_queue_draw (widget);
2787
2788       if ((default_size_changed || hints_changed) && (width != new_width || height != new_height))
2789         {
2790           /* We could be here for two reasons
2791            *  1) We coincidentally got a resize while handling
2792            *     another resize.
2793            *  2) Our computation of default_size_changed was completely
2794            *     screwed up, probably because one of our children
2795            *     is changed requisition during size allocation).
2796            *
2797            * For 1), we could just go ahead and ask for the
2798            * new size right now, but doing that for 2)
2799            * might well be fighting the user (and can even
2800            * trigger a loop). Since we really don't want to
2801            * do that, we requeue a resize in hopes that
2802            * by the time it gets handled, the child has seen
2803            * the light and is willing to go along with the
2804            * new size. (this happens for the zvt widget, since
2805            * the size_allocate() above will have stored the
2806            * requisition corresponding to the new size in the
2807            * zvt widget)
2808            *
2809            * This doesn't buy us anything for 1), but it shouldn't
2810            * hurt us too badly, since it is what would have
2811            * happened if we had gotten the configure event before
2812            * the new size had been set.
2813            */
2814           
2815           if (need_reposition)
2816             {
2817               if (window->frame)
2818                 gdk_window_move (window->frame, x - window->frame_left, y - window->frame_top);
2819               else
2820                 gdk_window_move (GTK_WIDGET (window)->window, x, y);
2821             }
2822
2823           /* we have to preserve the values and flags that are used
2824            * for computation of default_size_changed and hints_changed
2825            */
2826           info->last = saved_last_info;
2827           
2828           gtk_widget_queue_resize (widget);
2829
2830           return;
2831         }
2832     }
2833
2834   /* Now set hints if necessary
2835    */
2836   if (hints_changed)
2837     gdk_window_set_geometry_hints (widget->window,
2838                                    &new_geometry,
2839                                    new_flags);
2840
2841   if ((default_size_changed || hints_changed) &&
2842       (width != new_width || height != new_height))
2843     {
2844       /* given that (width != new_width || height != new_height), we are in one
2845        * of the following situations:
2846        * 
2847        * default_size_changed
2848        *   our requisition has changed and we need a different window size,
2849        *   so we request it from the window manager.
2850        *
2851        * !default_size_changed
2852        *   the window manager wouldn't assign us the size we requested, in this
2853        *   case we don't try to request a new size with every resize.
2854        *
2855        * !default_size_changed && hints_changed
2856        *   the window manager rejects our size, but we have just changed the
2857        *   window manager hints, so there's a certain chance our request will
2858        *   be honoured this time, so we try again.
2859        */
2860       
2861       /* request a new window size */
2862       if (need_reposition)
2863         {
2864           if (window->frame)
2865             {
2866               gdk_window_move_resize (window->frame,
2867                                       x - window->frame_left, y - window->frame_top,
2868                                       new_width + window->frame_left + window->frame_right,
2869                                       new_height + window->frame_top + window->frame_bottom);
2870               gdk_window_resize (GTK_WIDGET (window)->window, new_width, new_height);
2871             }
2872           else
2873             gdk_window_move_resize (GTK_WIDGET (window)->window, x, y, new_width, new_height);
2874         }
2875       else
2876         {
2877           if (window->frame)
2878             gdk_window_resize (window->frame,
2879                                new_width + window->frame_left + window->frame_right,
2880                                new_height + window->frame_top + window->frame_bottom);
2881           gdk_window_resize (GTK_WIDGET (window)->window, new_width, new_height);
2882         }
2883       window->resize_count += 1;
2884       
2885       /* we are now awaiting the new configure event in response to our
2886        * resizing request. the configure event will cause a new resize
2887        * with ->handling_resize=TRUE.
2888        * until then, we want to
2889        * - discard expose events
2890        * - coalesce resizes for our children
2891        * - defer any window resizes until the configure event arrived
2892        * to achive this, we queue a resize for the window, but remove its
2893        * resizing handler, so resizing will not be handled from the next
2894        * idle handler but when the configure event arrives.
2895        *
2896        * FIXME: we should also dequeue the pending redraws here, since
2897        * we handle those ourselves in ->handling_resize==TRUE.
2898        */
2899       gtk_widget_queue_resize (GTK_WIDGET (container));
2900       if (container->resize_mode == GTK_RESIZE_QUEUE)
2901         _gtk_container_dequeue_resize_handler (container);
2902     }
2903   else
2904     {
2905       if (need_reposition)
2906         {
2907           if (window->frame)
2908             gdk_window_move (window->frame, x - window->frame_left, y - window->frame_top);
2909           else
2910             gdk_window_move (widget->window, x, y);
2911         }
2912
2913       if (container->resize_widgets)
2914         gtk_container_resize_children (GTK_CONTAINER (window));
2915     }
2916 }
2917
2918 /* Compare two sets of Geometry hints for equality.
2919  */
2920 static gboolean
2921 gtk_window_compare_hints (GdkGeometry *geometry_a,
2922                           guint        flags_a,
2923                           GdkGeometry *geometry_b,
2924                           guint        flags_b)
2925 {
2926   if (flags_a != flags_b)
2927     return FALSE;
2928   
2929   if ((flags_a & GDK_HINT_MIN_SIZE) &&
2930       (geometry_a->min_width != geometry_b->min_width ||
2931        geometry_a->min_height != geometry_b->min_height))
2932     return FALSE;
2933
2934   if ((flags_a & GDK_HINT_MAX_SIZE) &&
2935       (geometry_a->max_width != geometry_b->max_width ||
2936        geometry_a->max_height != geometry_b->max_height))
2937     return FALSE;
2938
2939   if ((flags_a & GDK_HINT_BASE_SIZE) &&
2940       (geometry_a->base_width != geometry_b->base_width ||
2941        geometry_a->base_height != geometry_b->base_height))
2942     return FALSE;
2943
2944   if ((flags_a & GDK_HINT_ASPECT) &&
2945       (geometry_a->min_aspect != geometry_b->min_aspect ||
2946        geometry_a->max_aspect != geometry_b->max_aspect))
2947     return FALSE;
2948
2949   if ((flags_a & GDK_HINT_RESIZE_INC) &&
2950       (geometry_a->width_inc != geometry_b->width_inc ||
2951        geometry_a->height_inc != geometry_b->height_inc))
2952     return FALSE;
2953
2954   if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
2955       geometry_a->win_gravity != geometry_b->win_gravity)
2956     return FALSE;
2957
2958   return TRUE;
2959 }
2960
2961 /* Compute the default_size for a window. The result will
2962  * be stored in *width and *height. The default size is
2963  * the size the window should have when initially mapped.
2964  * This routine does not attempt to constrain the size
2965  * to obey the geometry hints - that must be done elsewhere.
2966  */
2967 static void 
2968 gtk_window_compute_default_size (GtkWindow       *window,
2969                                  guint           *width,
2970                                  guint           *height)
2971 {
2972   GtkRequisition requisition;
2973   GtkWindowGeometryInfo *info;
2974   
2975   gtk_widget_get_child_requisition (GTK_WIDGET (window), &requisition);
2976   *width = requisition.width;
2977   *height = requisition.height;
2978
2979   info = gtk_window_get_geometry_info (window, FALSE);
2980   
2981   if (*width == 0 && *height == 0)
2982     {
2983       /* empty window */
2984       *width = 200;
2985       *height = 200;
2986     }
2987   
2988   if (info)
2989     {
2990       *width = info->width > 0 ? info->width : *width;
2991       *height = info->height > 0 ? info->height : *height;
2992     }
2993 }
2994
2995 void
2996 _gtk_window_constrain_size (GtkWindow   *window,
2997                             gint         width,
2998                             gint         height,
2999                             gint        *new_width,
3000                             gint        *new_height)
3001 {
3002   GtkWindowGeometryInfo *info;
3003
3004   g_return_if_fail (GTK_IS_WINDOW (window));
3005
3006   info = window->geometry_info;
3007   if (info)
3008     {
3009       GdkWindowHints flags = info->last.flags;
3010       GdkGeometry *geometry = &info->last.geometry;
3011       
3012       gtk_window_constrain_size (window,
3013                                  geometry,
3014                                  flags,
3015                                  width,
3016                                  height,
3017                                  new_width,
3018                                  new_height);
3019     }
3020 }
3021
3022 static void 
3023 gtk_window_constrain_size (GtkWindow   *window,
3024                            GdkGeometry *geometry,
3025                            guint        flags,
3026                            gint         width,
3027                            gint         height,
3028                            gint        *new_width,
3029                            gint        *new_height)
3030 {
3031   gdk_window_constrain_size (geometry, flags, width, height,
3032                              new_width, new_height);
3033 }
3034
3035 /* Compute the set of geometry hints and flags for a window
3036  * based on the application set geometry, and requisiition
3037  * of the window. gtk_widget_size_request() must have been
3038  * called first.
3039  */
3040 static void
3041 gtk_window_compute_hints (GtkWindow   *window,
3042                           GdkGeometry *new_geometry,
3043                           guint       *new_flags)
3044 {
3045   GtkWidget *widget;
3046   GtkWidgetAuxInfo *aux_info;
3047   gint ux, uy;
3048   gint extra_width = 0;
3049   gint extra_height = 0;
3050   GtkWindowGeometryInfo *geometry_info;
3051   GtkRequisition requisition;
3052
3053   g_return_if_fail (GTK_IS_WINDOW (window));
3054
3055   widget = GTK_WIDGET (window);
3056   
3057   gtk_widget_get_child_requisition (widget, &requisition);
3058   geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
3059
3060   g_return_if_fail (geometry_info != NULL);
3061   
3062   *new_flags = geometry_info->mask;
3063   *new_geometry = geometry_info->geometry;
3064   
3065   if (geometry_info->widget)
3066     {
3067       extra_width = widget->requisition.width - geometry_info->widget->requisition.width;
3068       extra_height = widget->requisition.height - geometry_info->widget->requisition.height;
3069     }
3070   
3071   ux = 0;
3072   uy = 0;
3073   
3074   aux_info = _gtk_widget_get_aux_info (widget, FALSE);
3075   if (aux_info && aux_info->x_set && aux_info->y_set)
3076     {
3077       ux = aux_info->x;
3078       uy = aux_info->y;
3079       *new_flags |= GDK_HINT_POS;
3080     }
3081   
3082   if (*new_flags & GDK_HINT_BASE_SIZE)
3083     {
3084       new_geometry->base_width += extra_width;
3085       new_geometry->base_height += extra_height;
3086     }
3087   else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
3088            (*new_flags & GDK_HINT_RESIZE_INC) &&
3089            ((extra_width != 0) || (extra_height != 0)))
3090     {
3091       *new_flags |= GDK_HINT_BASE_SIZE;
3092       
3093       new_geometry->base_width = extra_width;
3094       new_geometry->base_height = extra_height;
3095     }
3096   
3097   if (*new_flags & GDK_HINT_MIN_SIZE)
3098     {
3099       if (new_geometry->min_width < 0)
3100         new_geometry->min_width = requisition.width;
3101       else
3102         new_geometry->min_width += extra_width;
3103
3104       if (new_geometry->min_height < 0)
3105         new_geometry->min_width = requisition.height;
3106       else
3107         new_geometry->min_height += extra_height;
3108     }
3109   else if (!window->allow_shrink)
3110     {
3111       *new_flags |= GDK_HINT_MIN_SIZE;
3112       
3113       new_geometry->min_width = requisition.width;
3114       new_geometry->min_height = requisition.height;
3115     }
3116   
3117   if (*new_flags & GDK_HINT_MAX_SIZE)
3118     {
3119       if (new_geometry->max_width < 0)
3120         new_geometry->max_width = requisition.width;
3121       else
3122         new_geometry->max_width += extra_width;
3123
3124       if (new_geometry->max_height < 0)
3125         new_geometry->max_width = requisition.height;
3126       else
3127         new_geometry->max_height += extra_height;
3128     }
3129   else if (!window->allow_grow)
3130     {
3131       *new_flags |= GDK_HINT_MAX_SIZE;
3132       
3133       new_geometry->max_width = requisition.width;
3134       new_geometry->max_height = requisition.height;
3135     }
3136
3137   *new_flags |= GDK_HINT_WIN_GRAVITY;
3138   new_geometry->win_gravity = window->gravity;
3139 }
3140
3141 /* Compute a new position for the window based on a new
3142  * size. *x and *y will be set to the new coordinates. Returns
3143  * TRUE if the window needs to be moved (and thus x and y got
3144  * assigned)
3145  */
3146 static gint
3147 gtk_window_compute_reposition (GtkWindow *window,
3148                                gint       new_width,
3149                                gint       new_height,
3150                                gint      *x,
3151                                gint      *y)
3152 {
3153   GtkWidget *widget = GTK_WIDGET (window);
3154   GtkWindowPosition pos;
3155   GtkWidget *parent_widget;
3156   gboolean needs_move = FALSE;
3157
3158   parent_widget = (GtkWidget*) window->transient_parent;
3159   
3160   pos = window->position;
3161   if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
3162       (parent_widget == NULL ||
3163        !GTK_WIDGET_MAPPED (parent_widget)))
3164     pos = GTK_WIN_POS_NONE;
3165   
3166   switch (pos)
3167   {
3168     case GTK_WIN_POS_CENTER:
3169     case GTK_WIN_POS_CENTER_ALWAYS:
3170       if (window->use_uposition)
3171         {
3172           gint screen_width = gdk_screen_width ();
3173           gint screen_height = gdk_screen_height ();
3174           
3175           *x = (screen_width - new_width) / 2;
3176           *y = (screen_height - new_height) / 2;
3177           needs_move = TRUE;
3178         }
3179       break;
3180
3181     case GTK_WIN_POS_CENTER_ON_PARENT:
3182       if (window->use_uposition)
3183         {
3184           gint ox, oy;
3185           gdk_window_get_origin (parent_widget->window,
3186                                    &ox, &oy);
3187                                  
3188           *x = ox + (parent_widget->allocation.width - new_width) / 2;
3189           *y = oy + (parent_widget->allocation.height - new_height) / 2;
3190           needs_move = TRUE;
3191         }
3192       break;
3193
3194     case GTK_WIN_POS_MOUSE:
3195       if (window->use_uposition)
3196         {
3197           gint screen_width = gdk_screen_width ();
3198           gint screen_height = gdk_screen_height ();
3199           
3200           gdk_window_get_pointer (NULL, x, y, NULL);
3201           *x -= new_width / 2;
3202           *y -= new_height / 2;
3203           *x = CLAMP (*x, 0, screen_width - new_width);
3204           *y = CLAMP (*y, 0, screen_height - new_height);
3205           needs_move = TRUE;
3206         }
3207       break;
3208     default:
3209       if (window->use_uposition)
3210         {
3211           GtkWidgetAuxInfo *aux_info = _gtk_widget_get_aux_info (widget, FALSE);
3212
3213           if (aux_info && aux_info->x_set && aux_info->y_set)
3214             {
3215               *x = aux_info->x;
3216               *y = aux_info->y;
3217               needs_move = TRUE;
3218             }
3219         }
3220       break;
3221     }
3222
3223   if (needs_move)
3224     {
3225       GtkWidgetAuxInfo *aux_info = _gtk_widget_get_aux_info (widget, TRUE);
3226
3227       /* we handle necessary window positioning by hand here,
3228        * so we can coalesce the window movement with possible
3229        * resizes to get only one configure event.
3230        */
3231       aux_info->x_set = TRUE;
3232       aux_info->y_set = TRUE;
3233       aux_info->x = *x;
3234       aux_info->y = *y;
3235       window->use_uposition = FALSE;
3236     }
3237
3238   return needs_move;
3239 }
3240
3241 /***********************
3242  * Redrawing functions *
3243  ***********************/
3244
3245 static void
3246 gtk_window_paint (GtkWidget     *widget,
3247                   GdkRectangle *area)
3248 {
3249   gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL, 
3250                       GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
3251 }
3252
3253 static gint
3254 gtk_window_expose (GtkWidget      *widget,
3255                    GdkEventExpose *event)
3256 {
3257   g_return_val_if_fail (widget != NULL, FALSE);
3258   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
3259   g_return_val_if_fail (event != NULL, FALSE);
3260
3261   if (!GTK_WIDGET_APP_PAINTABLE (widget))
3262     gtk_window_paint (widget, &event->area);
3263   
3264   if (GTK_WIDGET_CLASS (parent_class)->expose_event)
3265     return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
3266
3267   return TRUE;
3268 }
3269
3270 /**
3271  * gtk_window_set_has_frame:
3272  * @window: a #GtkWindow
3273  * @setting: a boolean
3274  * 
3275  * If this function is called on a window with setting of TRUE, before
3276  * it is realized or showed, it will have a "frame" window around
3277  * widget->window, accessible in window->frame. Using the signal 
3278  * frame_event you can recieve all events targeted at the frame.
3279  * 
3280  * This function is used by the linux-fb port to implement managed
3281  * windows, but it could concievably be used by X-programs that
3282  * want to do their own window decorations.
3283  **/
3284 void
3285 gtk_window_set_has_frame (GtkWindow *window, 
3286                           gboolean   setting)
3287 {
3288   g_return_if_fail (window != NULL);
3289   g_return_if_fail (GTK_IS_WINDOW (window));
3290   g_return_if_fail (!GTK_WIDGET_REALIZED (window));
3291
3292   window->has_frame = setting != FALSE;
3293 }
3294
3295 /**
3296  * gtk_window_get_has_frame:
3297  * @window: a #GtkWindow
3298  * 
3299  * Returns whether the window has a frame window exterior to
3300  * widget->window. See gtk_window_set_has_frame ().
3301  *
3302  * Return value: %TRUE if a frame has been added to the window
3303  *   via gtk_widow_has_frame
3304  **/
3305 gboolean
3306 gtk_window_get_has_frame (GtkWindow *window)
3307 {
3308   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3309
3310   return window->has_frame;
3311 }
3312
3313 /**
3314  * gtk_window_set_frame_dimensions:
3315  * @window: a #GtkWindow that has a frame
3316  * @left: The width of the left border
3317  * @top: The height of the top border
3318  * @right: The width of the right border
3319  * @bottom: The height of the bottom border
3320  *
3321  * For windows with frames (see #gtk_window_set_has_frame) this function
3322  * can be used to change the size of the frame border.
3323  **/
3324 void
3325 gtk_window_set_frame_dimensions (GtkWindow *window, 
3326                                  gint       left,
3327                                  gint       top,
3328                                  gint       right,
3329                                  gint       bottom)
3330 {
3331   GtkWidget *widget = GTK_WIDGET (window);
3332
3333   g_return_if_fail (window != NULL);
3334   g_return_if_fail (GTK_IS_WINDOW (window));
3335
3336   if (window->frame_left == left &&
3337       window->frame_top == top &&
3338       window->frame_right == right && 
3339       window->frame_bottom == bottom)
3340     return;
3341
3342   window->frame_left = left;
3343   window->frame_top = top;
3344   window->frame_right = right;
3345   window->frame_bottom = bottom;
3346
3347   if (GTK_WIDGET_REALIZED (widget) && window->frame)
3348     {
3349       gint width = widget->allocation.width + left + right;
3350       gint height = widget->allocation.height + top + bottom;
3351       gdk_window_resize (window->frame, width, height);
3352       gtk_decorated_window_move_resize_window (window,
3353                                                left, top,
3354                                                widget->allocation.width,
3355                                                widget->allocation.height);
3356     }
3357 }
3358
3359 /**
3360  * gtk_window_present:
3361  * @window: a #GtkWindow
3362  *
3363  * Presents a window to the user. This may mean raising the window
3364  * in the stacking order, deiconifying it, moving it to the current
3365  * desktop, and/or giving it the keyboard focus, possibly dependent
3366  * on the user's platform, window manager, and preferences.
3367  *
3368  * If @window is hidden, this function calls gtk_widget_show()
3369  * as well.
3370  * 
3371  * This function should be used when the user tries to open a window
3372  * that's already open. Say for example the preferences dialog is
3373  * currently open, and the user chooses Preferences from the menu
3374  * a second time; use gtk_window_present() to move the already-open dialog
3375  * where the user can see it.
3376  * 
3377  **/
3378 void
3379 gtk_window_present (GtkWindow *window)
3380 {
3381   GtkWidget *widget;
3382
3383   g_return_if_fail (GTK_IS_WINDOW (window));
3384
3385   widget = GTK_WIDGET (window);
3386
3387   if (GTK_WIDGET_VISIBLE (window))
3388     {
3389       g_assert (widget->window != NULL);
3390       
3391       gdk_window_show (widget->window);
3392
3393       /* note that gdk_window_focus() will also move the window to
3394        * the current desktop, for WM spec compliant window managers.
3395        */
3396       gdk_window_focus (widget->window,
3397                         gtk_get_current_event_time ());
3398     }
3399   else
3400     {
3401       gtk_widget_show (widget);
3402     }
3403 }
3404
3405 /**
3406  * gtk_window_iconify:
3407  * @window: a #GtkWindow
3408  *
3409  * Asks to iconify (i.e. minimize) the specified @window. Note that you
3410  * shouldn't assume the window is definitely iconified afterward,
3411  * because other entities (e.g. the user or window manager) could
3412  * deiconify it again, or there may not be a window manager in which
3413  * case iconification isn't possible, etc. But normally the window
3414  * will end up iconified. Just don't write code that crashes if not.
3415  *
3416  * It's permitted to call this function before showing a window,
3417  * in which case the window will be iconified before it ever appears
3418  * onscreen.
3419  *
3420  * You can track iconification via the "window_state_event" signal
3421  * on #GtkWidget.
3422  * 
3423  **/
3424 void
3425 gtk_window_iconify (GtkWindow *window)
3426 {
3427   GtkWidget *widget;
3428   GdkWindow *toplevel;
3429   
3430   g_return_if_fail (GTK_IS_WINDOW (window));
3431
3432   widget = GTK_WIDGET (window);
3433
3434   window->iconify_initially = TRUE;
3435
3436   if (window->frame)
3437     toplevel = window->frame;
3438   else
3439     toplevel = widget->window;
3440   
3441   if (toplevel != NULL)
3442     gdk_window_iconify (toplevel);
3443 }
3444
3445 /**
3446  * gtk_window_deiconify:
3447  * @window: a #GtkWindow
3448  *
3449  * Asks to deiconify (i.e. unminimize) the specified @window. Note
3450  * that you shouldn't assume the window is definitely deiconified
3451  * afterward, because other entities (e.g. the user or window manager)
3452  * could iconify it again before your code which assumes
3453  * deiconification gets to run.
3454  *
3455  * You can track iconification via the "window_state_event" signal
3456  * on #GtkWidget.
3457  **/
3458 void
3459 gtk_window_deiconify (GtkWindow *window)
3460 {
3461   GtkWidget *widget;
3462   GdkWindow *toplevel;
3463   
3464   g_return_if_fail (GTK_IS_WINDOW (window));
3465
3466   widget = GTK_WIDGET (window);
3467
3468   window->iconify_initially = FALSE;
3469
3470   if (window->frame)
3471     toplevel = window->frame;
3472   else
3473     toplevel = widget->window;
3474   
3475   if (toplevel != NULL)
3476     gdk_window_deiconify (toplevel);
3477 }
3478
3479 /**
3480  * gtk_window_stick:
3481  * @window: a #GtkWindow
3482  *
3483  * Asks to stick @window, which means that it will appear on all user
3484  * desktops. Note that you shouldn't assume the window is definitely
3485  * stuck afterward, because other entities (e.g. the user or window
3486  * manager) could unstick it again, and some window managers do not
3487  * support sticking windows. But normally the window will end up
3488  * stuck. Just don't write code that crashes if not.
3489  *
3490  * It's permitted to call this function before showing a window.
3491  *
3492  * You can track stickiness via the "window_state_event" signal
3493  * on #GtkWidget.
3494  * 
3495  **/
3496 void
3497 gtk_window_stick (GtkWindow *window)
3498 {
3499   GtkWidget *widget;
3500   GdkWindow *toplevel;
3501   
3502   g_return_if_fail (GTK_IS_WINDOW (window));
3503
3504   widget = GTK_WIDGET (window);
3505
3506   window->stick_initially = TRUE;
3507
3508   if (window->frame)
3509     toplevel = window->frame;
3510   else
3511     toplevel = widget->window;
3512   
3513   if (toplevel != NULL)
3514     gdk_window_stick (toplevel);
3515 }
3516
3517 /**
3518  * gtk_window_unstick:
3519  * @window: a #GtkWindow
3520  *
3521  * Asks to unstick @window, which means that it will appear on only
3522  * one of the user's desktops. Note that you shouldn't assume the
3523  * window is definitely unstuck afterward, because other entities
3524  * (e.g. the user or window manager) could stick it again. But
3525  * normally the window will end up stuck. Just don't write code that
3526  * crashes if not.
3527  *
3528  * You can track stickiness via the "window_state_event" signal
3529  * on #GtkWidget.
3530  * 
3531  **/
3532 void
3533 gtk_window_unstick (GtkWindow *window)
3534 {
3535   GtkWidget *widget;
3536   GdkWindow *toplevel;
3537   
3538   g_return_if_fail (GTK_IS_WINDOW (window));
3539
3540   widget = GTK_WIDGET (window);
3541
3542   window->stick_initially = FALSE;
3543
3544   if (window->frame)
3545     toplevel = window->frame;
3546   else
3547     toplevel = widget->window;
3548   
3549   if (toplevel != NULL)
3550     gdk_window_unstick (toplevel);
3551 }
3552
3553 /**
3554  * gtk_window_maximize:
3555  * @window: a #GtkWindow
3556  *
3557  * Asks to maximize @window, so that it becomes full-screen. Note that
3558  * you shouldn't assume the window is definitely maximized afterward,
3559  * because other entities (e.g. the user or window manager) could
3560  * unmaximize it again, and not all window managers support
3561  * maximization. But normally the window will end up maximized. Just
3562  * don't write code that crashes if not.
3563  *
3564  * It's permitted to call this function before showing a window,
3565  * in which case the window will be maximized when it appears onscreen
3566  * initially.
3567  *
3568  * You can track maximization via the "window_state_event" signal
3569  * on #GtkWidget.
3570  * 
3571  **/
3572 void
3573 gtk_window_maximize (GtkWindow *window)
3574 {
3575   GtkWidget *widget;
3576   GdkWindow *toplevel;
3577   
3578   g_return_if_fail (GTK_IS_WINDOW (window));
3579
3580   widget = GTK_WIDGET (window);
3581
3582   window->maximize_initially = TRUE;
3583
3584   if (window->frame)
3585     toplevel = window->frame;
3586   else
3587     toplevel = widget->window;
3588   
3589   if (toplevel != NULL)
3590     gdk_window_maximize (toplevel);
3591 }
3592
3593 /**
3594  * gtk_window_unmaximize:
3595  * @window: a #GtkWindow
3596  *
3597  * Asks to unmaximize @window. Note that you shouldn't assume the
3598  * window is definitely unmaximized afterward, because other entities
3599  * (e.g. the user or window manager) could maximize it again, and not
3600  * all window managers honor requests to unmaximize. But normally the
3601  * window will end up unmaximized. Just don't write code that crashes
3602  * if not.
3603  *
3604  * You can track maximization via the "window_state_event" signal
3605  * on #GtkWidget.
3606  * 
3607  **/
3608 void
3609 gtk_window_unmaximize (GtkWindow *window)
3610 {
3611   GtkWidget *widget;
3612   GdkWindow *toplevel;
3613   
3614   g_return_if_fail (GTK_IS_WINDOW (window));
3615
3616   widget = GTK_WIDGET (window);
3617
3618   window->maximize_initially = FALSE;
3619
3620   if (window->frame)
3621     toplevel = window->frame;
3622   else
3623     toplevel = widget->window;
3624   
3625   if (toplevel != NULL)
3626     gdk_window_unmaximize (toplevel);
3627 }
3628
3629 /**
3630  * gtk_window_set_resizable:
3631  * @window: a #GtkWindow
3632  * @resizable: %TRUE if the user can resize this window
3633  *
3634  * Sets whether the user can resize a window. Windows are user resizable
3635  * by default.
3636  **/
3637 void
3638 gtk_window_set_resizable (GtkWindow *window,
3639                           gboolean   resizable)
3640 {
3641   g_return_if_fail (GTK_IS_WINDOW (window));
3642
3643   gtk_window_set_policy (window, FALSE, resizable, FALSE);
3644 }
3645
3646 /**
3647  * gtk_window_get_resizable:
3648  * @window: a #GtkWindow
3649  *
3650  * Gets the value set by gtk_window_set_resizable().
3651  *
3652  * Return value: %TRUE if the user can resize the window
3653  **/
3654 gboolean
3655 gtk_window_get_resizable (GtkWindow *window)
3656 {
3657   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
3658
3659   /* allow_grow is most likely to indicate the semantic concept we
3660    * mean by "resizable" (and will be a reliable indicator if
3661    * set_policy() hasn't been called)
3662    */
3663   return window->allow_grow;
3664 }
3665
3666 /**
3667  * gtk_window_set_gravity:
3668  * @window: a #GtkWindow
3669  * @gravity: window gravity
3670  *
3671  * Window gravity defines the "reference point" to be used when
3672  * positioning or resizing a window. Calls to
3673  * gtk_widget_set_uposition() will position a different point on the
3674  * window depending on the window gravity. When the window changes size
3675  * the reference point determined by the window's gravity will stay in
3676  * a fixed location.
3677  *
3678  * See #GdkGravity for full details. To briefly summarize,
3679  * #GDK_GRAVITY_NORTH_WEST means that the reference point is the
3680  * northwest (top left) corner of the window
3681  * frame. #GDK_GRAVITY_SOUTH_EAST would be the bottom right corner of
3682  * the frame, and so on. If you want to position the window contents,
3683  * rather than the window manager's frame, #GDK_GRAVITY_STATIC moves
3684  * the reference point to the northwest corner of the #GtkWindow
3685  * itself.
3686  *
3687  * The default window gravity is #GDK_GRAVITY_NORTH_WEST.
3688  *
3689  **/
3690 void
3691 gtk_window_set_gravity (GtkWindow *window,
3692                         GdkGravity gravity)
3693 {
3694   g_return_if_fail (GTK_IS_WINDOW (window));
3695
3696   if (gravity != window->gravity)
3697     {
3698       window->gravity = gravity;
3699
3700       /* gtk_window_move_resize() will adapt gravity
3701        */
3702       gtk_widget_queue_resize (GTK_WIDGET (window));
3703     }
3704 }
3705
3706 /**
3707  * gtk_window_get_gravity:
3708  * @window: a #GtkWindow
3709  *
3710  * Gets the value set by gtk_window_set_gravity().
3711  *
3712  * Return value: window gravity
3713  **/
3714 GdkGravity
3715 gtk_window_get_gravity (GtkWindow *window)
3716 {
3717   g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
3718
3719   return window->gravity;
3720 }
3721
3722 /**
3723  * gtk_window_begin_resize_drag:
3724  * @window: a #GtkWindow
3725  * @button: mouse button that initiated the drag
3726  * @edge: position of the resize control
3727  * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
3728  * @root_y: Y position where the user clicked to initiate the drag
3729  * @timestamp: timestamp from the click event that initiated the drag
3730  *
3731  * Starts resizing a window. This function is used if an application
3732  * has window resizing controls. When GDK can support it, the resize
3733  * will be done using the standard mechanism for the window manager or
3734  * windowing system. Otherwise, GDK will try to emulate window
3735  * resizing, potentially not all that well, depending on the windowing system.
3736  * 
3737  **/
3738 void
3739 gtk_window_begin_resize_drag  (GtkWindow    *window,
3740                                GdkWindowEdge edge,
3741                                gint          button,
3742                                gint          root_x,
3743                                gint          root_y,
3744                                guint32       timestamp)
3745 {
3746   GtkWidget *widget;
3747   GdkWindow *toplevel;
3748   
3749   g_return_if_fail (GTK_IS_WINDOW (window));
3750   g_return_if_fail (GTK_WIDGET_VISIBLE (window));
3751   
3752   widget = GTK_WIDGET (window);
3753   
3754   if (window->frame)
3755     toplevel = window->frame;
3756   else
3757     toplevel = widget->window;
3758   
3759   gdk_window_begin_resize_drag (toplevel,
3760                                 edge, button,
3761                                 root_x, root_y,
3762                                 timestamp);
3763 }
3764
3765 /**
3766  * gtk_window_get_frame_dimensions:
3767  * @window: a #GtkWindow
3768  * @left: location to store the width of the frame at the left, or %NULL
3769  * @top: location to store the height of the frame at the top, or %NULL
3770  * @right: location to store the width of the frame at the returns, or %NULL
3771  * @bottom: location to store the height of the frame at the bottom, or %NULL
3772  *
3773  * Retrieves the dimensions of the frame window for this toplevel.
3774  * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
3775  **/
3776 void
3777 gtk_window_get_frame_dimensions (GtkWindow *window,
3778                                  gint      *left,
3779                                  gint      *top,
3780                                  gint      *right,
3781                                  gint      *bottom)
3782 {
3783   g_return_if_fail (GTK_IS_WINDOW (window));
3784
3785   if (left)
3786     *left = window->frame_left;
3787   if (top)
3788     *top = window->frame_top;
3789   if (right)
3790     *top = window->frame_right;
3791   if (bottom)
3792     *top = window->frame_bottom;
3793 }
3794
3795 /**
3796  * gtk_window_begin_move_drag:
3797  * @window: a #GtkWindow
3798  * @button: mouse button that initiated the drag
3799  * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
3800  * @root_y: Y position where the user clicked to initiate the drag
3801  * @timestamp: timestamp from the click event that initiated the drag
3802  *
3803  * Starts moving a window. This function is used if an application
3804  * has window movement grips. When GDK can support it, the window movement
3805  * will be done using the standard mechanism for the window manager or
3806  * windowing system. Otherwise, GDK will try to emulate window
3807  * movement, potentially not all that well, depending on the windowing system.
3808  * 
3809  **/
3810 void
3811 gtk_window_begin_move_drag  (GtkWindow *window,
3812                              gint       button,
3813                              gint       root_x,
3814                              gint       root_y,
3815                              guint32    timestamp)
3816 {
3817   GtkWidget *widget;
3818   GdkWindow *toplevel;
3819   
3820   g_return_if_fail (GTK_IS_WINDOW (window));
3821   g_return_if_fail (GTK_WIDGET_VISIBLE (window));
3822   
3823   widget = GTK_WIDGET (window);
3824   
3825   if (window->frame)
3826     toplevel = window->frame;
3827   else
3828     toplevel = widget->window;
3829   
3830   gdk_window_begin_move_drag (toplevel,
3831                               button,
3832                               root_x, root_y,
3833                               timestamp);
3834 }
3835
3836
3837 static void
3838 gtk_window_group_class_init (GtkWindowGroupClass *klass)
3839 {
3840 }
3841
3842 GtkType
3843 gtk_window_group_get_type (void)
3844 {
3845   static GtkType window_group_type = 0;
3846
3847   if (!window_group_type)
3848     {
3849       static const GTypeInfo window_group_info =
3850       {
3851         sizeof (GtkWindowGroupClass),
3852         NULL,           /* base_init */
3853         NULL,           /* base_finalize */
3854         (GClassInitFunc) gtk_window_group_class_init,
3855         NULL,           /* class_finalize */
3856         NULL,           /* class_data */
3857         sizeof (GtkWindowGroup),
3858         16,             /* n_preallocs */
3859         (GInstanceInitFunc) NULL,
3860       };
3861
3862       window_group_type = g_type_register_static (G_TYPE_OBJECT, "GtkWindowGroup", &window_group_info, 0);
3863     }
3864
3865   return window_group_type;
3866 }
3867
3868 /**
3869  * gtk_window_group_new:
3870  * 
3871  * Create a new #GtkWindowGroup object. Grabs added with
3872  * gtk_window_grab_add() only affect windows within the
3873  * same #GtkWindowGroup
3874  * 
3875  * Return value: 
3876  **/
3877 GtkWindowGroup *
3878 gtk_window_group_new (void)
3879 {
3880   return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
3881 }
3882
3883 static void
3884 window_group_cleanup_grabs (GtkWindowGroup *group,
3885                             GtkWindow      *window)
3886 {
3887   GSList *tmp_list;
3888   GSList *to_remove = NULL;
3889
3890   tmp_list = group->grabs;
3891   while (tmp_list)
3892     {
3893       if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
3894         to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
3895       tmp_list = tmp_list->next;
3896     }
3897
3898   while (to_remove)
3899     {
3900       gtk_grab_remove (to_remove->data);
3901       g_object_unref (to_remove->data);
3902       to_remove = g_slist_delete_link (to_remove, to_remove);
3903     }
3904 }
3905
3906 /**
3907  * gtk_window_group_add_widget:
3908  * @window_group: a #GtkWindowGroup
3909  * @window: the #GtkWindow to add
3910  * 
3911  * Add a window to a #GtkWindowGroup. 
3912  **/
3913 void
3914 gtk_window_group_add_window (GtkWindowGroup *window_group,
3915                              GtkWindow      *window)
3916 {
3917   g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
3918   g_return_if_fail (GTK_IS_WINDOW (window));
3919
3920   if (window->group != window_group)
3921     {
3922       g_object_ref (window);
3923       g_object_ref (window_group);
3924       
3925       if (window->group)
3926         gtk_window_group_remove_window (window->group, window);
3927       else
3928         window_group_cleanup_grabs (_gtk_window_get_group (NULL), window);
3929
3930       window->group = window_group;
3931
3932       g_object_unref (window);
3933     }
3934 }
3935
3936 /**
3937  * gtk_window_group_remove_window:
3938  * @window_group: a #GtkWindowGroup
3939  * @window: the #GtkWindow to remove
3940  * 
3941  * Removes a window from a #GtkWindowGroup.
3942  **/
3943 void
3944 gtk_window_group_remove_window (GtkWindowGroup *window_group,
3945                                 GtkWindow      *window)
3946 {
3947   g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
3948   g_return_if_fail (GTK_IS_WIDGET (window));
3949   g_return_if_fail (window->group == window_group);
3950
3951   g_object_ref (window);
3952
3953   window_group_cleanup_grabs (window_group, window);
3954   window->group = NULL;
3955   
3956   g_object_unref (G_OBJECT (window_group));
3957   g_object_unref (window);
3958 }
3959
3960 /* Return the group for the window or the default group
3961  */
3962 GtkWindowGroup *
3963 _gtk_window_get_group (GtkWindow *window)
3964 {
3965   if (window && window->group)
3966     return window->group;
3967   else
3968     {
3969       static GtkWindowGroup *default_group = NULL;
3970
3971       if (!default_group)
3972         default_group = gtk_window_group_new ();
3973
3974       return default_group;
3975     }
3976 }