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