]> Pileus Git - ~andy/gtk/blob - gtk/gtkwindow.c
warn about &widget->requisition, even for toplevels.
[~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 Library 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  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library 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-1999.  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 #include "gdk/gdkx.h"
32 #include "gtkprivate.h"
33 #include "gtkrc.h"
34 #include "gtksignal.h"
35 #include "gtkwindow.h"
36 #include "gtkbindings.h"
37 #include "gtkmain.h"
38
39 enum {
40   SET_FOCUS,
41   LAST_SIGNAL
42 };
43 enum {
44   ARG_0,
45   ARG_TYPE,
46   ARG_TITLE,
47   ARG_AUTO_SHRINK,
48   ARG_ALLOW_SHRINK,
49   ARG_ALLOW_GROW,
50   ARG_MODAL,
51   ARG_WIN_POS
52 };
53
54 typedef struct {
55   GdkGeometry    geometry;
56   GdkWindowHints mask;
57   GtkWidget     *widget;
58   gint           width;
59   gint           height;
60   gint           last_width;
61   gint           last_height;
62 } GtkWindowGeometryInfo;
63
64 static void gtk_window_class_init         (GtkWindowClass    *klass);
65 static void gtk_window_init               (GtkWindow         *window);
66 static void gtk_window_set_arg            (GtkObject         *object,
67                                            GtkArg            *arg,
68                                            guint              arg_id);
69 static void gtk_window_get_arg            (GtkObject         *object,
70                                            GtkArg            *arg,
71                                            guint              arg_id);
72 static void gtk_window_shutdown           (GtkObject         *object);
73 static void gtk_window_destroy            (GtkObject         *object);
74 static void gtk_window_finalize           (GtkObject         *object);
75 static void gtk_window_show               (GtkWidget         *widget);
76 static void gtk_window_hide               (GtkWidget         *widget);
77 static void gtk_window_map                (GtkWidget         *widget);
78 static void gtk_window_unmap              (GtkWidget         *widget);
79 static void gtk_window_realize            (GtkWidget         *widget);
80 static void gtk_window_size_request       (GtkWidget         *widget,
81                                            GtkRequisition    *requisition);
82 static void gtk_window_size_allocate      (GtkWidget         *widget,
83                                            GtkAllocation     *allocation);
84 static gint gtk_window_configure_event    (GtkWidget         *widget,
85                                            GdkEventConfigure *event);
86 static gint gtk_window_key_press_event    (GtkWidget         *widget,
87                                            GdkEventKey       *event);
88 static gint gtk_window_key_release_event  (GtkWidget         *widget,
89                                            GdkEventKey       *event);
90 static gint gtk_window_enter_notify_event (GtkWidget         *widget,
91                                            GdkEventCrossing  *event);
92 static gint gtk_window_leave_notify_event (GtkWidget         *widget,
93                                            GdkEventCrossing  *event);
94 static gint gtk_window_focus_in_event     (GtkWidget         *widget,
95                                            GdkEventFocus     *event);
96 static gint gtk_window_focus_out_event    (GtkWidget         *widget,
97                                            GdkEventFocus     *event);
98 static gint gtk_window_client_event       (GtkWidget         *widget,
99                                            GdkEventClient    *event);
100 static void gtk_window_check_resize       (GtkContainer      *container);
101 static void gtk_window_real_set_focus     (GtkWindow         *window,
102                                            GtkWidget         *focus);
103 static void gtk_window_move_resize        (GtkWindow         *window);
104 static void gtk_window_set_hints          (GtkWidget         *widget,
105                                            GtkRequisition    *requisition);
106
107 static void gtk_window_read_rcfiles       (GtkWidget         *widget,
108                                            GdkEventClient    *event);
109 static void gtk_window_draw               (GtkWidget         *widget,
110                                            GdkRectangle      *area);
111 static void gtk_window_paint              (GtkWidget         *widget,
112                                            GdkRectangle      *area);
113 static gint gtk_window_expose             (GtkWidget         *widget,
114                                            GdkEventExpose    *event);
115 static void gtk_window_unset_transient_for         (GtkWindow  *window);
116 static void gtk_window_transient_parent_realized   (GtkWidget  *parent,
117                                                     GtkWidget  *window);
118 static void gtk_window_transient_parent_unrealized (GtkWidget  *parent,
119                                                     GtkWidget  *window);
120
121 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
122                                                             gboolean   create);
123 static void gtk_window_geometry_destroy  (GtkWindowGeometryInfo *info);
124
125 static GtkBinClass *parent_class = NULL;
126 static guint window_signals[LAST_SIGNAL] = { 0 };
127
128
129 GtkType
130 gtk_window_get_type (void)
131 {
132   static GtkType window_type = 0;
133
134   if (!window_type)
135     {
136       static const GtkTypeInfo window_info =
137       {
138         "GtkWindow",
139         sizeof (GtkWindow),
140         sizeof (GtkWindowClass),
141         (GtkClassInitFunc) gtk_window_class_init,
142         (GtkObjectInitFunc) gtk_window_init,
143         /* reserved_1 */ NULL,
144         /* reserved_2 */ NULL,
145         (GtkClassInitFunc) NULL,
146       };
147
148       window_type = gtk_type_unique (gtk_bin_get_type (), &window_info);
149     }
150
151   return window_type;
152 }
153
154 static void
155 gtk_window_class_init (GtkWindowClass *klass)
156 {
157   GtkObjectClass *object_class;
158   GtkWidgetClass *widget_class;
159   GtkContainerClass *container_class;
160
161   object_class = (GtkObjectClass*) klass;
162   widget_class = (GtkWidgetClass*) klass;
163   container_class = (GtkContainerClass*) klass;
164
165   parent_class = gtk_type_class (gtk_bin_get_type ());
166
167   gtk_object_add_arg_type ("GtkWindow::type", GTK_TYPE_WINDOW_TYPE, GTK_ARG_READWRITE, ARG_TYPE);
168   gtk_object_add_arg_type ("GtkWindow::title", GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_TITLE);
169   gtk_object_add_arg_type ("GtkWindow::auto_shrink", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_AUTO_SHRINK);
170   gtk_object_add_arg_type ("GtkWindow::allow_shrink", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_ALLOW_SHRINK);
171   gtk_object_add_arg_type ("GtkWindow::allow_grow", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_ALLOW_GROW);
172   gtk_object_add_arg_type ("GtkWindow::modal", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_MODAL);
173   gtk_object_add_arg_type ("GtkWindow::window_position", GTK_TYPE_WINDOW_POSITION, GTK_ARG_READWRITE, ARG_WIN_POS);
174
175   window_signals[SET_FOCUS] =
176     gtk_signal_new ("set_focus",
177                     GTK_RUN_LAST,
178                     object_class->type,
179                     GTK_SIGNAL_OFFSET (GtkWindowClass, set_focus),
180                     gtk_marshal_NONE__POINTER,
181                     GTK_TYPE_NONE, 1,
182                     GTK_TYPE_WIDGET);
183
184   gtk_object_class_add_signals (object_class, window_signals, LAST_SIGNAL);
185
186   object_class->set_arg = gtk_window_set_arg;
187   object_class->get_arg = gtk_window_get_arg;
188   object_class->shutdown = gtk_window_shutdown;
189   object_class->destroy = gtk_window_destroy;
190   object_class->finalize = gtk_window_finalize;
191
192   widget_class->show = gtk_window_show;
193   widget_class->hide = gtk_window_hide;
194   widget_class->map = gtk_window_map;
195   widget_class->unmap = gtk_window_unmap;
196   widget_class->realize = gtk_window_realize;
197   widget_class->size_request = gtk_window_size_request;
198   widget_class->size_allocate = gtk_window_size_allocate;
199   widget_class->configure_event = gtk_window_configure_event;
200   widget_class->key_press_event = gtk_window_key_press_event;
201   widget_class->key_release_event = gtk_window_key_release_event;
202   widget_class->enter_notify_event = gtk_window_enter_notify_event;
203   widget_class->leave_notify_event = gtk_window_leave_notify_event;
204   widget_class->focus_in_event = gtk_window_focus_in_event;
205   widget_class->focus_out_event = gtk_window_focus_out_event;
206   widget_class->client_event = gtk_window_client_event;
207
208   widget_class->draw = gtk_window_draw;
209   widget_class->expose_event = gtk_window_expose;
210    
211   container_class->check_resize = gtk_window_check_resize;
212
213   klass->set_focus = gtk_window_real_set_focus;
214 }
215
216 static void
217 gtk_window_init (GtkWindow *window)
218 {
219   GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
220   GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
221
222   gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
223
224   window->title = NULL;
225   window->wmclass_name = g_strdup (g_get_prgname ());
226   window->wmclass_class = g_strdup (gdk_progclass);
227   window->type = GTK_WINDOW_TOPLEVEL;
228   window->focus_widget = NULL;
229   window->default_widget = NULL;
230   window->resize_count = 0;
231   window->allow_shrink = FALSE;
232   window->allow_grow = TRUE;
233   window->auto_shrink = FALSE;
234   window->handling_resize = FALSE;
235   window->position = GTK_WIN_POS_NONE;
236   window->use_uposition = TRUE;
237   window->modal = FALSE;
238   
239   gtk_container_register_toplevel (GTK_CONTAINER (window));
240 }
241
242 static void
243 gtk_window_set_arg (GtkObject  *object,
244                     GtkArg     *arg,
245                     guint       arg_id)
246 {
247   GtkWindow  *window;
248
249   window = GTK_WINDOW (object);
250
251   switch (arg_id)
252     {
253     case ARG_TYPE:
254       window->type = GTK_VALUE_ENUM (*arg);
255       break;
256     case ARG_TITLE:
257       gtk_window_set_title (window, GTK_VALUE_STRING (*arg));
258       break;
259     case ARG_AUTO_SHRINK:
260       window->auto_shrink = (GTK_VALUE_BOOL (*arg) != FALSE);
261       gtk_window_set_hints (GTK_WIDGET (window), &GTK_WIDGET (window)->requisition);
262       break;
263     case ARG_ALLOW_SHRINK:
264       window->allow_shrink = (GTK_VALUE_BOOL (*arg) != FALSE);
265       gtk_window_set_hints (GTK_WIDGET (window), &GTK_WIDGET (window)->requisition);
266       break;
267     case ARG_ALLOW_GROW:
268       window->allow_grow = (GTK_VALUE_BOOL (*arg) != FALSE);
269       gtk_window_set_hints (GTK_WIDGET (window), &GTK_WIDGET (window)->requisition);
270       break;
271     case ARG_MODAL:
272       gtk_window_set_modal (window, GTK_VALUE_BOOL (*arg));
273       break;
274     case ARG_WIN_POS:
275       gtk_window_set_position (window, GTK_VALUE_ENUM (*arg));
276       break;
277     default:
278       break;
279     }
280 }
281
282 static void
283 gtk_window_get_arg (GtkObject  *object,
284                     GtkArg     *arg,
285                     guint       arg_id)
286 {
287   GtkWindow  *window;
288
289   window = GTK_WINDOW (object);
290
291   switch (arg_id)
292     {
293     case ARG_TYPE:
294       GTK_VALUE_ENUM (*arg) = window->type;
295       break;
296     case ARG_TITLE:
297       GTK_VALUE_STRING (*arg) = g_strdup (window->title);
298       break;
299     case ARG_AUTO_SHRINK:
300       GTK_VALUE_BOOL (*arg) = window->auto_shrink;
301       break;
302     case ARG_ALLOW_SHRINK:
303       GTK_VALUE_BOOL (*arg) = window->allow_shrink;
304       break;
305     case ARG_ALLOW_GROW:
306       GTK_VALUE_BOOL (*arg) = window->allow_grow;
307       break;
308     case ARG_MODAL:
309       GTK_VALUE_BOOL (*arg) = window->modal;
310       break;
311     case ARG_WIN_POS:
312       GTK_VALUE_ENUM (*arg) = window->position;
313       break;
314     default:
315       arg->type = GTK_TYPE_INVALID;
316       break;
317     }
318 }
319
320 GtkWidget*
321 gtk_window_new (GtkWindowType type)
322 {
323   GtkWindow *window;
324
325   window = gtk_type_new (gtk_window_get_type ());
326
327   window->type = type;
328
329   return GTK_WIDGET (window);
330 }
331
332 void
333 gtk_window_set_title (GtkWindow   *window,
334                       const gchar *title)
335 {
336   g_return_if_fail (window != NULL);
337   g_return_if_fail (GTK_IS_WINDOW (window));
338
339   if (window->title)
340     g_free (window->title);
341   window->title = g_strdup (title);
342
343   if (GTK_WIDGET_REALIZED (window))
344     gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
345 }
346
347 void
348 gtk_window_set_wmclass (GtkWindow *window,
349                         const gchar *wmclass_name,
350                         const gchar *wmclass_class)
351 {
352   g_return_if_fail (window != NULL);
353   g_return_if_fail (GTK_IS_WINDOW (window));
354
355   g_free (window->wmclass_name);
356   window->wmclass_name = g_strdup (wmclass_name);
357
358   g_free (window->wmclass_class);
359   window->wmclass_class = g_strdup (wmclass_class);
360
361   if (GTK_WIDGET_REALIZED (window))
362     g_warning ("shouldn't set wmclass after window is realized!\n");
363 }
364
365 void
366 gtk_window_set_focus (GtkWindow *window,
367                       GtkWidget *focus)
368 {
369   g_return_if_fail (window != NULL);
370   g_return_if_fail (GTK_IS_WINDOW (window));
371   if (focus)
372     {
373       g_return_if_fail (GTK_IS_WIDGET (focus));
374       g_return_if_fail (GTK_WIDGET_CAN_FOCUS (focus));
375     }
376
377   if ((window->focus_widget != focus) ||
378       (focus && !GTK_WIDGET_HAS_FOCUS (focus)))
379     gtk_signal_emit (GTK_OBJECT (window), window_signals[SET_FOCUS], focus);
380 }
381
382 void
383 gtk_window_set_default (GtkWindow *window,
384                         GtkWidget *default_widget)
385 {
386   g_return_if_fail (window != NULL);
387   g_return_if_fail (GTK_IS_WINDOW (window));
388
389   if (default_widget)
390     g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
391
392   if (window->default_widget != default_widget)
393     {
394       if (window->default_widget)
395         {
396           GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
397           gtk_widget_draw_default (window->default_widget);
398         }
399
400       window->default_widget = default_widget;
401
402       if (window->default_widget)
403         {
404           GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
405           gtk_widget_draw_default (window->default_widget);
406         }
407     }
408 }
409
410 void
411 gtk_window_set_policy (GtkWindow *window,
412                        gint       allow_shrink,
413                        gint       allow_grow,
414                        gint       auto_shrink)
415 {
416   g_return_if_fail (window != NULL);
417   g_return_if_fail (GTK_IS_WINDOW (window));
418
419   window->allow_shrink = (allow_shrink != FALSE);
420   window->allow_grow = (allow_grow != FALSE);
421   window->auto_shrink = (auto_shrink != FALSE);
422
423   gtk_window_set_hints (GTK_WIDGET (window), &GTK_WIDGET (window)->requisition);
424 }
425
426 void
427 gtk_window_add_accel_group (GtkWindow        *window,
428                             GtkAccelGroup    *accel_group)
429 {
430   g_return_if_fail (window != NULL);
431   g_return_if_fail (GTK_IS_WINDOW (window));
432   g_return_if_fail (accel_group != NULL);
433
434   gtk_accel_group_attach (accel_group, GTK_OBJECT (window));
435 }
436
437 void
438 gtk_window_remove_accel_group (GtkWindow       *window,
439                                GtkAccelGroup   *accel_group)
440 {
441   g_return_if_fail (window != NULL);
442   g_return_if_fail (GTK_IS_WINDOW (window));
443   g_return_if_fail (accel_group != NULL);
444
445   gtk_accel_group_detach (accel_group, GTK_OBJECT (window));
446 }
447
448 void
449 gtk_window_set_position (GtkWindow         *window,
450                          GtkWindowPosition  position)
451 {
452   g_return_if_fail (window != NULL);
453   g_return_if_fail (GTK_IS_WINDOW (window));
454
455   window->position = position;
456 }
457
458 gint
459 gtk_window_activate_focus (GtkWindow      *window)
460 {
461   g_return_val_if_fail (window != NULL, FALSE);
462   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
463
464   if (window->focus_widget)
465     {
466       gtk_widget_activate (window->focus_widget);
467       return TRUE;
468     }
469
470   return FALSE;
471 }
472
473 gint
474 gtk_window_activate_default (GtkWindow      *window)
475 {
476   g_return_val_if_fail (window != NULL, FALSE);
477   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
478
479   if (window->default_widget)
480     {
481       gtk_widget_activate (window->default_widget);
482       return TRUE;
483     }
484
485   return FALSE;
486 }
487
488 void
489 gtk_window_set_modal (GtkWindow *window,
490                       gboolean   modal)
491 {
492   g_return_if_fail (window != NULL);
493   g_return_if_fail (GTK_IS_WINDOW (window));
494
495   window->modal = modal != FALSE;
496
497   /* adjust desired modality state */
498   if (GTK_WIDGET_VISIBLE (window) && window->modal)
499     gtk_grab_add (GTK_WIDGET (window));
500   else
501     gtk_grab_remove (GTK_WIDGET (window));
502 }
503
504 void
505 gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
506 {
507   GList *embedded_windows;
508
509   g_return_if_fail (window != NULL);
510   g_return_if_fail (GTK_IS_WINDOW (window));
511
512   embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
513   if (embedded_windows)
514     gtk_object_remove_no_notify_by_id (GTK_OBJECT (window), 
515                                        g_quark_from_static_string ("gtk-embedded"));
516   embedded_windows = g_list_prepend (embedded_windows,
517                                      GUINT_TO_POINTER (xid));
518
519   gtk_object_set_data_full (GTK_OBJECT (window), "gtk-embedded", 
520                             embedded_windows,
521                             embedded_windows ?
522                               (GtkDestroyNotify) g_list_free : NULL);
523 }
524
525 void
526 gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
527 {
528   GList *embedded_windows;
529   GList *node;
530
531   g_return_if_fail (window != NULL);
532   g_return_if_fail (GTK_IS_WINDOW (window));
533   
534   embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
535   if (embedded_windows)
536     gtk_object_remove_no_notify_by_id (GTK_OBJECT (window), 
537                                        g_quark_from_static_string ("gtk-embedded"));
538
539   node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
540   if (node)
541     {
542       embedded_windows = g_list_remove_link (embedded_windows, node);
543       g_list_free_1 (node);
544     }
545   
546   gtk_object_set_data_full (GTK_OBJECT (window), 
547                             "gtk-embedded", embedded_windows,
548                             embedded_windows ?
549                               (GtkDestroyNotify) g_list_free : NULL);
550 }
551
552 static void
553 gtk_window_shutdown (GtkObject *object)
554 {
555   GtkWindow *window;
556
557   g_return_if_fail (object != NULL);
558   g_return_if_fail (GTK_IS_WINDOW (object));
559
560   window = GTK_WINDOW (object);
561
562   gtk_window_set_focus (window, NULL);
563   gtk_window_set_default (window, NULL);
564
565   GTK_OBJECT_CLASS (parent_class)->shutdown (object);
566 }
567
568 static void
569 gtk_window_transient_parent_realized (GtkWidget *parent,
570                                       GtkWidget *window)
571 {
572   if (GTK_WIDGET_REALIZED (window))
573     gdk_window_set_transient_for (window->window, parent->window);
574 }
575
576 static void
577 gtk_window_transient_parent_unrealized (GtkWidget *parent,
578                                         GtkWidget *window)
579 {
580   if (GTK_WIDGET_REALIZED (window))
581     gdk_property_delete (window->window, 
582                          gdk_atom_intern ("WM_TRANSIENT_FOR", FALSE));
583 }
584
585 static void       
586 gtk_window_unset_transient_for  (GtkWindow *window)
587 {
588   if (window->transient_parent)
589     {
590       gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
591                                      GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
592                                      window);
593       gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
594                                      GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
595                                      window);
596       gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
597                                      GTK_SIGNAL_FUNC (gtk_widget_destroyed),
598                                      &window->transient_parent);
599
600       window->transient_parent = NULL;
601     }
602 }
603
604 void       
605 gtk_window_set_transient_for  (GtkWindow *window, 
606                                GtkWindow *parent)
607 {
608   g_return_if_fail (window != 0);
609
610   if (window->transient_parent)
611     {
612       gtk_window_unset_transient_for (window);
613       
614       if (GTK_WIDGET_REALIZED (window) && 
615           GTK_WIDGET_REALIZED (window->transient_parent) && 
616           (!parent || !GTK_WIDGET_REALIZED (parent)))
617         gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
618                                                 GTK_WIDGET (window));
619     }
620
621   window->transient_parent = parent;
622
623   if (parent)
624     {
625       gtk_signal_connect (GTK_OBJECT (parent), "destroy",
626                           GTK_SIGNAL_FUNC (gtk_widget_destroyed),
627                           &window->transient_parent);
628       gtk_signal_connect (GTK_OBJECT (parent), "realize",
629                           GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
630                           window);
631       gtk_signal_connect (GTK_OBJECT (parent), "unrealize",
632                           GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
633                           window);
634
635       if (GTK_WIDGET_REALIZED (window) &&
636           GTK_WIDGET_REALIZED (parent))
637         gtk_window_transient_parent_realized (GTK_WIDGET (parent),
638                                               GTK_WIDGET (window));
639     }
640 }
641
642 static void
643 gtk_window_geometry_destroy (GtkWindowGeometryInfo *info)
644 {
645   if (info->widget)
646     gtk_signal_disconnect_by_func (GTK_OBJECT (info->widget),
647                                    GTK_SIGNAL_FUNC (gtk_widget_destroyed),
648                                    &info->widget);
649   g_free (info);
650 }
651
652 static GtkWindowGeometryInfo *
653 gtk_window_get_geometry_info (GtkWindow *window, gboolean create)
654 {
655   GtkWindowGeometryInfo *info;
656
657   info = gtk_object_get_data (GTK_OBJECT (window), "gtk-window-geometry");
658
659   if (!info && create)
660     {
661       info = g_new (GtkWindowGeometryInfo, 1);
662
663       info->width = - 1;
664       info->height = -1;
665       info->last_width = -1;
666       info->last_height = -1;
667       info->widget = NULL;
668       info->mask = 0;
669
670       gtk_object_set_data_full (GTK_OBJECT (window), 
671                                 
672                                 "gtk-window-geometry",
673                                 info, 
674                                 (GtkDestroyNotify) gtk_window_geometry_destroy);
675     }
676
677   return info;
678 }
679
680 void       
681 gtk_window_set_geometry_hints (GtkWindow       *window,
682                                GtkWidget       *geometry_widget,
683                                GdkGeometry     *geometry,
684                                GdkWindowHints   geom_mask)
685 {
686   GtkWindowGeometryInfo *info;
687
688   g_return_if_fail (window != NULL);
689
690   info = gtk_window_get_geometry_info (window, TRUE);
691   
692   if (info->widget)
693     gtk_signal_disconnect_by_func (GTK_OBJECT (info->widget),
694                                    GTK_SIGNAL_FUNC (gtk_widget_destroyed),
695                                    &info->widget);
696   
697   info->widget = geometry_widget;
698   if (info->widget)
699     gtk_signal_connect (GTK_OBJECT (geometry_widget), "destroy",
700                         GTK_SIGNAL_FUNC (gtk_widget_destroyed),
701                         &info->widget);
702
703   if (geometry)
704     info->geometry = *geometry;
705
706   info->mask = geom_mask;
707 }
708
709 void       
710 gtk_window_set_default_size (GtkWindow   *window,
711                              gint         width,
712                              gint         height)
713 {
714   GtkWindowGeometryInfo *info;
715
716   g_return_if_fail (window != NULL);
717
718   info = gtk_window_get_geometry_info (window, TRUE);
719
720   info->width = width;
721   info->height = height;
722 }
723   
724 static void
725 gtk_window_destroy (GtkObject *object)
726 {
727   GtkWindow *window;
728   
729   g_return_if_fail (object != NULL);
730   g_return_if_fail (GTK_IS_WINDOW (object));
731
732   window = GTK_WINDOW (object);
733   
734   gtk_container_unregister_toplevel (GTK_CONTAINER (object));
735
736   if (window->transient_parent)
737     gtk_window_unset_transient_for (window);
738
739   GTK_OBJECT_CLASS (parent_class)->destroy (object);
740 }
741
742 static void
743 gtk_window_finalize (GtkObject *object)
744 {
745   GtkWindow *window;
746
747   g_return_if_fail (object != NULL);
748   g_return_if_fail (GTK_IS_WINDOW (object));
749
750   window = GTK_WINDOW (object);
751   g_free (window->title);
752   g_free (window->wmclass_name);
753   g_free (window->wmclass_class);
754
755   GTK_OBJECT_CLASS(parent_class)->finalize (object);
756 }
757
758 static void
759 gtk_window_show (GtkWidget *widget)
760 {
761   g_return_if_fail (widget != NULL);
762   g_return_if_fail (GTK_IS_WINDOW (widget));
763
764   GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
765   gtk_container_check_resize (GTK_CONTAINER (widget));
766   gtk_widget_map (widget);
767
768   if (GTK_WINDOW (widget)->modal)
769     gtk_grab_add (widget);
770 }
771
772 static void
773 gtk_window_hide (GtkWidget *widget)
774 {
775   GtkWindow *window;
776
777   g_return_if_fail (widget != NULL);
778   g_return_if_fail (GTK_IS_WINDOW (widget));
779
780   window = GTK_WINDOW (widget);
781
782   GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
783   gtk_widget_unmap (widget);
784
785   if (window->modal)
786     gtk_grab_remove (widget);
787 }
788
789 static void
790 gtk_window_map (GtkWidget *widget)
791 {
792   GtkWindow *window;
793
794   g_return_if_fail (widget != NULL);
795   g_return_if_fail (GTK_IS_WINDOW (widget));
796
797   GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
798
799   window = GTK_WINDOW (widget);
800
801   if (window->bin.child &&
802       GTK_WIDGET_VISIBLE (window->bin.child) &&
803       !GTK_WIDGET_MAPPED (window->bin.child))
804     gtk_widget_map (window->bin.child);
805
806   gtk_window_set_hints (widget, &widget->requisition);
807   gdk_window_show (widget->window);
808 }
809
810 static void
811 gtk_window_unmap (GtkWidget *widget)
812 {
813   GtkWindow *window;
814
815   g_return_if_fail (widget != NULL);
816   g_return_if_fail (GTK_IS_WINDOW (widget));
817
818   GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
819   gdk_window_hide (widget->window);
820
821   window = GTK_WINDOW (widget);
822   window->use_uposition = TRUE;
823 }
824
825 static void
826 gtk_window_realize (GtkWidget *widget)
827 {
828   GtkWindow *window;
829   GdkWindowAttr attributes;
830   gint attributes_mask;
831   
832   g_return_if_fail (widget != NULL);
833   g_return_if_fail (GTK_IS_WINDOW (widget));
834   
835   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
836   window = GTK_WINDOW (widget);
837   
838   switch (window->type)
839     {
840     case GTK_WINDOW_TOPLEVEL:
841       attributes.window_type = GDK_WINDOW_TOPLEVEL;
842       break;
843     case GTK_WINDOW_DIALOG:
844       attributes.window_type = GDK_WINDOW_DIALOG;
845       break;
846     case GTK_WINDOW_POPUP:
847       attributes.window_type = GDK_WINDOW_TEMP;
848       break;
849     }
850    
851   attributes.title = window->title;
852   attributes.wmclass_name = window->wmclass_name;
853   attributes.wmclass_class = window->wmclass_class;
854   attributes.width = widget->allocation.width;
855   attributes.height = widget->allocation.height;
856   attributes.wclass = GDK_INPUT_OUTPUT;
857   attributes.visual = gtk_widget_get_visual (widget);
858   attributes.colormap = gtk_widget_get_colormap (widget);
859   attributes.event_mask = gtk_widget_get_events (widget);
860   attributes.event_mask |= (GDK_EXPOSURE_MASK |
861                             GDK_KEY_PRESS_MASK |
862                             GDK_ENTER_NOTIFY_MASK |
863                             GDK_LEAVE_NOTIFY_MASK |
864                             GDK_FOCUS_CHANGE_MASK |
865                             GDK_STRUCTURE_MASK);
866    
867   attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
868   attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
869   attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
870    
871   widget->window = gdk_window_new (NULL, &attributes, attributes_mask);
872   gdk_window_set_user_data (widget->window, window);
873
874   widget->style = gtk_style_attach (widget->style, widget->window);
875   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
876   gtk_window_paint (widget, NULL);
877
878   if (window->transient_parent &&
879       GTK_WIDGET_REALIZED (window->transient_parent))
880     gdk_window_set_transient_for (widget->window,
881                                   GTK_WIDGET (window->transient_parent)->window);
882 }
883
884 static void
885 gtk_window_size_request (GtkWidget      *widget,
886                          GtkRequisition *requisition)
887 {
888   GtkWindow *window;
889   GtkBin *bin;
890
891   g_return_if_fail (widget != NULL);
892   g_return_if_fail (GTK_IS_WINDOW (widget));
893   g_return_if_fail (requisition != NULL);
894
895   window = GTK_WINDOW (widget);
896   bin = GTK_BIN (window);
897   
898   requisition->width = GTK_CONTAINER (window)->border_width * 2;
899   requisition->height = GTK_CONTAINER (window)->border_width * 2;
900
901   if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
902     {
903       GtkRequisition child_requisition;
904       
905       gtk_widget_size_request (bin->child, &child_requisition);
906
907       requisition->width += child_requisition.width;
908       requisition->height += child_requisition.height;
909     }
910   else
911     {
912       if (!GTK_WIDGET_VISIBLE (window))
913         GTK_CONTAINER (window)->need_resize = TRUE;
914     }
915 }
916
917 static void
918 gtk_window_size_allocate (GtkWidget     *widget,
919                           GtkAllocation *allocation)
920 {
921   GtkWindow *window;
922   GtkAllocation child_allocation;
923
924   g_return_if_fail (widget != NULL);
925   g_return_if_fail (GTK_IS_WINDOW (widget));
926   g_return_if_fail (allocation != NULL);
927
928   window = GTK_WINDOW (widget);
929   widget->allocation = *allocation;
930
931   if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
932     {
933       child_allocation.x = GTK_CONTAINER (window)->border_width;
934       child_allocation.y = GTK_CONTAINER (window)->border_width;
935       child_allocation.width = allocation->width - child_allocation.x * 2;
936       child_allocation.height = allocation->height - child_allocation.y * 2;
937
938       gtk_widget_size_allocate (window->bin.child, &child_allocation);
939     }
940 }
941
942 static gint
943 gtk_window_configure_event (GtkWidget         *widget,
944                             GdkEventConfigure *event)
945 {
946   GtkWindow *window;
947   GtkAllocation allocation;
948   gboolean need_expose = FALSE;
949   
950   g_return_val_if_fail (widget != NULL, FALSE);
951   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
952   g_return_val_if_fail (event != NULL, FALSE);
953   
954   window = GTK_WINDOW (widget);
955
956   /* If the window was merely moved, do nothing */
957   if ((widget->allocation.width == event->width) &&
958       (widget->allocation.height == event->height))
959     {
960       if (window->resize_count == 0)      /* The window was merely moved */
961         return FALSE;
962       else
963         {
964           /* We asked for a new size, which was rejected, so the
965            * WM sent us a synthetic configure event. We won't
966            * get the expose event we would normally get (since
967            * we have ForgetGravity), so we need to fake it.
968            */
969           need_expose = TRUE;
970         }
971     }
972         
973   
974   window->handling_resize = TRUE;
975   
976   allocation.x = 0;
977   allocation.y = 0;
978   allocation.width = event->width;
979   allocation.height = event->height;
980   
981   gtk_widget_size_allocate (widget, &allocation);
982   
983   if (window->bin.child &&
984       GTK_WIDGET_VISIBLE (window->bin.child) &&
985       !GTK_WIDGET_MAPPED (window->bin.child))
986     gtk_widget_map (window->bin.child);
987   
988   if (window->resize_count > 0)
989       window->resize_count -= 1;
990   
991   if (need_expose)
992     {
993       GdkEvent temp_event;
994       temp_event.type = GDK_EXPOSE;
995       temp_event.expose.window = widget->window;
996       temp_event.expose.send_event = TRUE;
997       temp_event.expose.area.x = 0;
998       temp_event.expose.area.y = 0;
999       temp_event.expose.area.width = event->width;
1000       temp_event.expose.area.height = event->height;
1001       temp_event.expose.count = 0;
1002       
1003       gtk_widget_event (widget, &temp_event);
1004     }
1005
1006   window->handling_resize = FALSE;
1007   
1008   return FALSE;
1009 }
1010
1011 static gint
1012 gtk_window_key_press_event (GtkWidget   *widget,
1013                             GdkEventKey *event)
1014 {
1015   GtkWindow *window;
1016   GtkDirectionType direction = 0;
1017   gboolean handled;
1018
1019   g_return_val_if_fail (widget != NULL, FALSE);
1020   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1021   g_return_val_if_fail (event != NULL, FALSE);
1022
1023   window = GTK_WINDOW (widget);
1024
1025   handled = FALSE;
1026   
1027   if (window->focus_widget && GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1028     {
1029       handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
1030     }
1031     
1032   if (!handled)
1033     handled = gtk_accel_groups_activate (GTK_OBJECT (window), event->keyval, event->state);
1034
1035   if (!handled)
1036     {
1037       switch (event->keyval)
1038         {
1039         case GDK_space:
1040           if (window->focus_widget)
1041             {
1042               gtk_widget_activate (window->focus_widget);
1043               handled = TRUE;
1044             }
1045           break;
1046         case GDK_Return:
1047         case GDK_KP_Enter:
1048           if (window->default_widget &&
1049               (!window->focus_widget || 
1050                !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1051             {
1052               gtk_widget_activate (window->default_widget);
1053               handled = TRUE;
1054             }
1055           else if (window->focus_widget)
1056             {
1057               gtk_widget_activate (window->focus_widget);
1058               handled = TRUE;
1059             }
1060           break;
1061         case GDK_Up:
1062         case GDK_Down:
1063         case GDK_Left:
1064         case GDK_Right:
1065         case GDK_Tab:
1066         case GDK_ISO_Left_Tab:
1067           switch (event->keyval)
1068             {
1069             case GDK_Up:
1070               direction = GTK_DIR_UP;
1071               break;
1072             case GDK_Down:
1073               direction = GTK_DIR_DOWN;
1074               break;
1075             case GDK_Left:
1076               direction = GTK_DIR_LEFT;
1077               break;
1078             case GDK_Right:
1079               direction = GTK_DIR_RIGHT;
1080               break;
1081             case GDK_Tab:
1082             case GDK_ISO_Left_Tab:
1083               if (event->state & GDK_SHIFT_MASK)
1084                 direction = GTK_DIR_TAB_BACKWARD;
1085               else
1086                 direction = GTK_DIR_TAB_FORWARD;
1087               break;
1088             default :
1089               direction = GTK_DIR_UP; /* never reached, but makes compiler happy */
1090             }
1091
1092           gtk_container_focus (GTK_CONTAINER (widget), direction);
1093
1094           if (!GTK_CONTAINER (window)->focus_child)
1095             gtk_window_set_focus (GTK_WINDOW (widget), NULL);
1096           else
1097             handled = TRUE;
1098           break;
1099         }
1100     }
1101
1102   if (!handled && GTK_WIDGET_CLASS (parent_class)->key_press_event)
1103     handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
1104
1105   return handled;
1106 }
1107
1108 static gint
1109 gtk_window_key_release_event (GtkWidget   *widget,
1110                               GdkEventKey *event)
1111 {
1112   GtkWindow *window;
1113   gint handled;
1114   
1115   g_return_val_if_fail (widget != NULL, FALSE);
1116   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1117   g_return_val_if_fail (event != NULL, FALSE);
1118   
1119   window = GTK_WINDOW (widget);
1120   handled = FALSE;
1121   if (window->focus_widget && GTK_WIDGET_SENSITIVE (window->focus_widget))
1122     {
1123       handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
1124     }
1125
1126   if (!handled && GTK_WIDGET_CLASS (parent_class)->key_release_event)
1127     handled = GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
1128
1129   return handled;
1130 }
1131
1132 static gint
1133 gtk_window_enter_notify_event (GtkWidget        *widget,
1134                                GdkEventCrossing *event)
1135 {
1136   g_return_val_if_fail (widget != NULL, FALSE);
1137   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1138   g_return_val_if_fail (event != NULL, FALSE);
1139
1140   return FALSE;
1141 }
1142
1143 static gint
1144 gtk_window_leave_notify_event (GtkWidget        *widget,
1145                                GdkEventCrossing *event)
1146 {
1147   g_return_val_if_fail (widget != NULL, FALSE);
1148   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1149   g_return_val_if_fail (event != NULL, FALSE);
1150
1151   return FALSE;
1152 }
1153
1154 static gint
1155 gtk_window_focus_in_event (GtkWidget     *widget,
1156                            GdkEventFocus *event)
1157 {
1158   GtkWindow *window;
1159   GdkEventFocus fevent;
1160
1161   g_return_val_if_fail (widget != NULL, FALSE);
1162   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1163   g_return_val_if_fail (event != NULL, FALSE);
1164
1165   /* It appears spurious focus in events can occur when
1166    *  the window is hidden. So we'll just check to see if
1167    *  the window is visible before actually handling the
1168    *  event
1169    */
1170   if (GTK_WIDGET_VISIBLE (widget))
1171     {
1172       window = GTK_WINDOW (widget);
1173       if (window->focus_widget && !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
1174         {
1175           fevent.type = GDK_FOCUS_CHANGE;
1176           fevent.window = window->focus_widget->window;
1177           fevent.in = TRUE;
1178
1179           gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
1180         }
1181     }
1182
1183   return FALSE;
1184 }
1185
1186 static gint
1187 gtk_window_focus_out_event (GtkWidget     *widget,
1188                             GdkEventFocus *event)
1189 {
1190   GtkWindow *window;
1191   GdkEventFocus fevent;
1192
1193   g_return_val_if_fail (widget != NULL, FALSE);
1194   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1195   g_return_val_if_fail (event != NULL, FALSE);
1196
1197   window = GTK_WINDOW (widget);
1198   if (window->focus_widget && GTK_WIDGET_HAS_FOCUS (window->focus_widget))
1199     {
1200       fevent.type = GDK_FOCUS_CHANGE;
1201       fevent.window = window->focus_widget->window;
1202       fevent.in = FALSE;
1203
1204       gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
1205     }
1206
1207   return FALSE;
1208 }
1209
1210 static GdkAtom atom_rcfiles = GDK_NONE;
1211
1212 static void
1213 gtk_window_read_rcfiles (GtkWidget *widget,
1214                          GdkEventClient *event)
1215 {
1216   GList *embedded_windows;
1217
1218   embedded_windows = gtk_object_get_data (GTK_OBJECT (widget), "gtk-embedded");
1219   if (embedded_windows)
1220     {
1221       GdkEventClient sev;
1222       int i;
1223       
1224       for(i = 0; i < 5; i++)
1225         sev.data.l[i] = 0;
1226       sev.data_format = 32;
1227       sev.message_type = atom_rcfiles;
1228       
1229       while (embedded_windows)
1230         {
1231           guint xid = GPOINTER_TO_UINT (embedded_windows->data);
1232           gdk_event_send_client_message ((GdkEvent *) &sev, xid);
1233           embedded_windows = embedded_windows->next;
1234         }
1235     }
1236
1237   if (gtk_rc_reparse_all ())
1238     {
1239       /* If the above returned true, some of our RC files are out
1240        * of date, so we need to reset all our widgets. Our other
1241        * toplevel windows will also get the message, but by
1242        * then, the RC file will up to date, so we have to tell
1243        * them now.
1244        */
1245       GList *toplevels;
1246       
1247       toplevels = gtk_container_get_toplevels();
1248       while (toplevels)
1249         {
1250           gtk_widget_reset_rc_styles (toplevels->data);
1251           toplevels = toplevels->next;
1252         }
1253     }
1254 }
1255
1256 static gint
1257 gtk_window_client_event (GtkWidget      *widget,
1258                          GdkEventClient *event)
1259 {
1260   g_return_val_if_fail (widget != NULL, FALSE);
1261   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1262   g_return_val_if_fail (event != NULL, FALSE);
1263
1264   if (!atom_rcfiles)
1265     atom_rcfiles = gdk_atom_intern("_GTK_READ_RCFILES", FALSE);
1266
1267   if(event->message_type == atom_rcfiles) 
1268     gtk_window_read_rcfiles (widget, event);    
1269
1270   return FALSE;
1271 }
1272
1273 static void
1274 gtk_window_check_resize (GtkContainer *container)
1275 {
1276   GtkWindow *window;
1277
1278   g_return_if_fail (container != NULL);
1279   g_return_if_fail (GTK_IS_WINDOW (container));
1280
1281   window = GTK_WINDOW (container);
1282   if (!window->handling_resize)
1283     {
1284       if (GTK_WIDGET_VISIBLE (container))
1285         gtk_window_move_resize (window);
1286       else
1287         GTK_CONTAINER (window)->need_resize = TRUE;
1288     }
1289 }
1290
1291 /* FIXME: we leave container->resize_widgets set under some
1292    circumstances ? */
1293 static void
1294 gtk_window_move_resize (GtkWindow *window)
1295 {
1296   GtkWidget    *widget;
1297   GtkWindowGeometryInfo *info;
1298   GtkRequisition requisition;
1299   GtkContainer *container;
1300   gint x, y;
1301   gint width, height;
1302   gint new_width, new_height;
1303   gint min_width, min_height;
1304   gint screen_width;
1305   gint screen_height;
1306   gboolean needed_resize;
1307   gboolean size_changed;
1308
1309   g_return_if_fail (window != NULL);
1310   g_return_if_fail (GTK_IS_WINDOW (window));
1311
1312   widget = GTK_WIDGET (window);
1313   container = GTK_CONTAINER (widget);
1314
1315   info = gtk_window_get_geometry_info (window, FALSE);
1316   
1317   /* Remember old size, to know if we have to reset hints */
1318   if (info && (info->last_width > 0))
1319     width = info->last_width;
1320   else
1321     width = widget->requisition.width;
1322
1323   if (info && (info->last_height > 0))
1324     height = info->last_height;
1325   else
1326     height = widget->requisition.height;
1327
1328   size_changed = FALSE;
1329
1330   gtk_widget_size_request (widget, &requisition);
1331
1332   size_changed |= requisition.width != widget->requisition.width;
1333   size_changed |= requisition.height != widget->requisition.height;
1334   widget->requisition = requisition;
1335
1336   /* Figure out the new desired size */
1337
1338   if (info && info->width > 0)
1339     {
1340       size_changed |= width != info->last_width;
1341       info->last_width = width;
1342       new_width = info->width;
1343     }
1344   else
1345     {
1346       size_changed |= width != widget->requisition.width;
1347       new_width = widget->requisition.width;
1348     }
1349
1350   if (info && info->height > 0)
1351     {
1352       size_changed |= height != info->last_height;
1353       info->last_height = height;
1354       new_height = info->height;
1355     }
1356   else
1357     {
1358       size_changed |= height != widget->requisition.height;
1359       new_height = widget->requisition.height;
1360     }
1361
1362   /* Figure out the new minimum size */
1363
1364   if (info && (info->mask & (GDK_HINT_MIN_SIZE | GDK_HINT_BASE_SIZE)))
1365     {
1366       if (info->mask && GDK_HINT_MIN_SIZE)
1367         {
1368           min_width = info->geometry.min_width;
1369           min_height = info->geometry.min_height;
1370         }
1371       else
1372         {
1373           min_width = info->geometry.base_width;
1374           min_height = info->geometry.base_height;
1375         }
1376
1377       if (info->widget)
1378         {
1379           min_width += widget->requisition.width - info->widget->requisition.width;
1380           min_height += widget->requisition.height - info->widget->requisition.height;
1381         }
1382     }
1383   else
1384     {
1385       min_width = widget->requisition.width;
1386       min_height = widget->requisition.height;
1387     }
1388
1389   if (size_changed)
1390     {
1391       gboolean saved_use_upos;
1392
1393       saved_use_upos = window->use_uposition;
1394       gtk_window_set_hints (widget, &widget->requisition);
1395       window->use_uposition = saved_use_upos;
1396     }
1397   
1398   x = -1;
1399   y = -1;
1400   
1401   if (window->use_uposition)
1402     switch (window->position)
1403       {
1404       case GTK_WIN_POS_CENTER:
1405         x = (gdk_screen_width () - new_width) / 2;
1406         y = (gdk_screen_height () - new_height) / 2;
1407         gtk_widget_set_uposition (widget, x, y);
1408         break;
1409       case GTK_WIN_POS_MOUSE:
1410         gdk_window_get_pointer (NULL, &x, &y, NULL);
1411         
1412         x -= new_width / 2;
1413         y -= new_height / 2;
1414         
1415         screen_width = gdk_screen_width ();
1416         screen_height = gdk_screen_height ();
1417         
1418         if (x < 0)
1419           x = 0;
1420         else if (x > (screen_width - new_width))
1421           x = screen_width - new_width;
1422         
1423         if (y < 0)
1424           y = 0;
1425         else if (y > (screen_height - new_height))
1426           y = screen_height - new_height;
1427         
1428         gtk_widget_set_uposition (widget, x, y);
1429         break;
1430       }
1431
1432   /* Now, do the resizing */
1433
1434   needed_resize = container->need_resize;
1435   container->need_resize = FALSE;
1436
1437   if ((new_width == 0) || (new_height == 0))
1438     {
1439       new_width = 200;
1440       new_height = 200;
1441     }
1442   
1443   if (!GTK_WIDGET_REALIZED (window))
1444     {
1445       GtkAllocation allocation;
1446
1447       allocation.x = 0;
1448       allocation.y = 0;
1449       allocation.width = new_width;
1450       allocation.height = new_height;
1451       
1452       gtk_widget_size_allocate (widget, &allocation);
1453
1454       return;
1455     }
1456   
1457   gdk_window_get_geometry (widget->window, NULL, NULL, &width, &height, NULL);
1458   
1459   /* As an optimization, we don't try to get a new size from the
1460    * window manager if we asked for the same size last time and
1461    * didn't get it */
1462
1463   if (size_changed && 
1464       (((window->auto_shrink &&
1465         ((width != new_width) ||
1466          (height != new_height)))) ||
1467        ((width < min_width) ||
1468         (height < min_height))))
1469     {
1470       window->resize_count += 1;
1471
1472       if (!window->auto_shrink)
1473         {
1474           new_width = MAX(width, min_width);
1475           new_height = MAX(height, min_height);
1476         }
1477       
1478       if ((x != -1) && (y != -1))
1479         gdk_window_move_resize (widget->window, x, y,
1480                                 new_width,
1481                                 new_height);
1482       else
1483         gdk_window_resize (widget->window,
1484                            new_width,
1485                            new_height);
1486     }
1487   else if (needed_resize)
1488     {
1489       /* The windows contents changed size while it was not
1490        * visible, so reallocate everything, since we didn't
1491        * keep track of what changed
1492        */
1493       GtkAllocation allocation;
1494       
1495       allocation.x = 0;
1496       allocation.y = 0;
1497       allocation.width = new_width;
1498       allocation.height = new_height;
1499       
1500       gtk_widget_size_allocate (widget, &allocation);
1501       gdk_window_resize (widget->window,
1502                          new_width,
1503                          new_height);
1504     }
1505   else
1506     {
1507       if ((x != -1) && (y != -1))
1508         gdk_window_move (widget->window, x, y);
1509       
1510       gtk_container_resize_children (GTK_CONTAINER (window));
1511     }
1512 }
1513
1514 static void
1515 gtk_window_real_set_focus (GtkWindow *window,
1516                            GtkWidget *focus)
1517 {
1518   GdkEventFocus event;
1519   gboolean def_flags = 0;
1520
1521   g_return_if_fail (window != NULL);
1522   g_return_if_fail (GTK_IS_WINDOW (window));
1523   
1524   if (window->default_widget)
1525     def_flags = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
1526   
1527   if (window->focus_widget)
1528     {
1529       event.type = GDK_FOCUS_CHANGE;
1530       event.window = window->focus_widget->window;
1531       event.in = FALSE;
1532       
1533       if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
1534           (window->focus_widget != window->default_widget))
1535         {
1536           GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
1537           /* if any widget had the default set there should be
1538              a default_widget, but might not so this is a sanity
1539              check */
1540           if (window->default_widget)
1541             GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1542         }
1543         
1544       gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
1545     }
1546   
1547   window->focus_widget = focus;
1548   
1549   if (window->focus_widget)
1550     {
1551       event.type = GDK_FOCUS_CHANGE;
1552       event.window = window->focus_widget->window;
1553       event.in = TRUE;
1554
1555       if (window->default_widget)
1556         {
1557           if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
1558               (window->focus_widget != window->default_widget))
1559             {
1560               if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
1561                 GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
1562               GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1563             }
1564           else
1565             {
1566               GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1567             }
1568         }
1569       
1570       gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
1571     }
1572   else if (window->default_widget)
1573     {
1574       GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1575     }
1576   
1577   if (window->default_widget &&
1578       (def_flags != GTK_WIDGET_FLAGS (window->default_widget)))
1579     gtk_widget_queue_draw (window->default_widget);
1580 }
1581
1582 static void
1583 gtk_window_set_hints (GtkWidget      *widget,
1584                       GtkRequisition *requisition)
1585 {
1586   GtkWindow *window;
1587   GtkWidgetAuxInfo *aux_info;
1588   GtkWindowGeometryInfo *geometry_info;
1589   GdkGeometry new_geometry;
1590   gint flags;
1591   gint ux, uy;
1592   gint extra_width = 0;
1593   gint extra_height = 0;
1594
1595   g_return_if_fail (widget != NULL);
1596   g_return_if_fail (GTK_IS_WINDOW (widget));
1597   g_return_if_fail (requisition != NULL);
1598
1599   if (GTK_WIDGET_REALIZED (widget))
1600     {
1601       window = GTK_WINDOW (widget);
1602
1603       geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
1604
1605       if (geometry_info)
1606         {
1607           flags = geometry_info->mask;
1608           new_geometry = geometry_info->geometry;
1609
1610           if (geometry_info->widget)
1611             {
1612               extra_width = requisition->width - geometry_info->widget->requisition.width;
1613               extra_height = requisition->height - geometry_info->widget->requisition.height;
1614             }
1615         }
1616       else
1617         flags = 0;
1618       
1619       ux = 0;
1620       uy = 0;
1621
1622       aux_info = gtk_object_get_data (GTK_OBJECT (widget), "gtk-aux-info");
1623       if (aux_info && (aux_info->x != -1) && (aux_info->y != -1))
1624         {
1625           ux = aux_info->x;
1626           uy = aux_info->y;
1627           flags |= GDK_HINT_POS;
1628         }
1629       
1630       if (flags & GDK_HINT_BASE_SIZE)
1631         {
1632           new_geometry.base_width += extra_width;
1633           new_geometry.base_height += extra_height;
1634         }
1635       else if (!(flags & GDK_HINT_MIN_SIZE) &&
1636                (flags & GDK_HINT_RESIZE_INC) &&
1637                ((extra_width != 0) || (extra_height != 0)))
1638         {
1639           flags |= GDK_HINT_BASE_SIZE;
1640
1641           new_geometry.base_width = extra_width;
1642           new_geometry.base_height = extra_height;
1643         }
1644
1645       if (flags & GDK_HINT_MIN_SIZE)
1646         {
1647           new_geometry.min_width += extra_width;
1648           new_geometry.min_height += extra_height;
1649         }
1650       else if (!window->allow_shrink)
1651         {
1652           flags |= GDK_HINT_MIN_SIZE;
1653
1654           new_geometry.min_width = requisition->width;
1655           new_geometry.min_height = requisition->height;
1656         }
1657
1658       if (flags & GDK_HINT_MAX_SIZE)
1659         {
1660           new_geometry.max_width += extra_width;
1661           new_geometry.max_height += extra_height;
1662         }
1663       else if (!window->allow_grow)
1664         {
1665           flags |= GDK_HINT_MAX_SIZE;
1666
1667           new_geometry.max_width = requisition->width;
1668           new_geometry.max_height = requisition->height;
1669         }
1670
1671       gdk_window_set_geometry_hints (widget->window, &new_geometry, flags);
1672
1673       if (window->use_uposition && (flags & GDK_HINT_POS))
1674         {
1675           window->use_uposition = FALSE;
1676           gdk_window_move (widget->window, ux, uy);
1677         }
1678     }
1679 }
1680
1681 static void
1682 gtk_window_paint (GtkWidget     *widget,
1683                   GdkRectangle *area)
1684 {
1685   gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL, 
1686                       GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
1687 }
1688
1689 static gint
1690 gtk_window_expose (GtkWidget      *widget,
1691                    GdkEventExpose *event)
1692 {
1693   g_return_val_if_fail (widget != NULL, FALSE);
1694   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1695   g_return_val_if_fail (event != NULL, FALSE);
1696
1697   if (!GTK_WIDGET_APP_PAINTABLE (widget))
1698     gtk_window_paint (widget, &event->area);
1699   
1700   if (GTK_WIDGET_CLASS (parent_class)->expose_event)
1701     return (* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event);
1702
1703   return FALSE;
1704 }
1705
1706 static void
1707 gtk_window_draw (GtkWidget    *widget,
1708                  GdkRectangle *area)
1709 {
1710   if (!GTK_WIDGET_APP_PAINTABLE (widget))
1711     gtk_window_paint (widget, area);
1712   
1713   if (GTK_WIDGET_CLASS (parent_class)->draw)
1714     (* GTK_WIDGET_CLASS (parent_class)->draw) (widget, area);
1715 }