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