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