]> Pileus Git - ~andy/gtk/blob - gtk/gtkwindow.c
do not avoid to queue for a resize if the container is not visible, we
[~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
30 enum {
31   SET_FOCUS,
32   LAST_SIGNAL
33 };
34 enum {
35   ARG_0,
36   ARG_TYPE,
37   ARG_TITLE,
38   ARG_AUTO_SHRINK,
39   ARG_ALLOW_SHRINK,
40   ARG_ALLOW_GROW,
41   ARG_WIN_POS
42 };
43
44 typedef gint (*GtkWindowSignal1) (GtkObject *object,
45                                   gpointer   arg1,
46                                   gpointer   arg2,
47                                   gint       arg3,
48                                   gint       arg4,
49                                   gpointer   data);
50 typedef void (*GtkWindowSignal2) (GtkObject *object,
51                                   gpointer   arg1,
52                                   gpointer   data);
53
54 static void gtk_window_marshal_signal_2 (GtkObject      *object,
55                                          GtkSignalFunc   func,
56                                          gpointer        func_data,
57                                          GtkArg         *args);
58 static void gtk_window_class_init         (GtkWindowClass    *klass);
59 static void gtk_window_init               (GtkWindow         *window);
60 static void gtk_window_set_arg            (GtkWindow         *window,
61                                            GtkArg            *arg,
62                                            guint              arg_id);
63 static void gtk_window_get_arg            (GtkWindow         *window,
64                                            GtkArg            *arg,
65                                            guint              arg_id);
66 static void gtk_window_shutdown           (GtkObject         *object);
67 static void gtk_window_destroy            (GtkObject         *object);
68 static void gtk_window_finalize           (GtkObject         *object);
69 static void gtk_window_show               (GtkWidget         *widget);
70 static void gtk_window_hide               (GtkWidget         *widget);
71 static void gtk_window_map                (GtkWidget         *widget);
72 static void gtk_window_unmap              (GtkWidget         *widget);
73 static void gtk_window_realize            (GtkWidget         *widget);
74 static void gtk_window_size_request       (GtkWidget         *widget,
75                                            GtkRequisition    *requisition);
76 static void gtk_window_size_allocate      (GtkWidget         *widget,
77                                            GtkAllocation     *allocation);
78 static gint gtk_window_expose_event       (GtkWidget         *widget,
79                                            GdkEventExpose    *event);
80 static gint gtk_window_configure_event    (GtkWidget         *widget,
81                                            GdkEventConfigure *event);
82 static gint gtk_window_key_press_event    (GtkWidget         *widget,
83                                            GdkEventKey       *event);
84 static gint gtk_window_key_release_event  (GtkWidget         *widget,
85                                            GdkEventKey       *event);
86 static gint gtk_window_enter_notify_event (GtkWidget         *widget,
87                                            GdkEventCrossing  *event);
88 static gint gtk_window_leave_notify_event (GtkWidget         *widget,
89                                            GdkEventCrossing  *event);
90 static gint gtk_window_focus_in_event     (GtkWidget         *widget,
91                                            GdkEventFocus     *event);
92 static gint gtk_window_focus_out_event    (GtkWidget         *widget,
93                                            GdkEventFocus     *event);
94 static gint gtk_window_client_event       (GtkWidget         *widget,
95                                            GdkEventClient    *event);
96 static void gtk_window_check_resize       (GtkContainer      *container);
97 static void gtk_real_window_set_focus     (GtkWindow         *window,
98                                            GtkWidget         *focus);
99 static void gtk_window_move_resize        (GtkWindow         *window);
100 static void gtk_window_set_hints          (GtkWidget         *widget,
101                                            GtkRequisition    *requisition);
102
103 static void gtk_window_read_rcfiles       (GtkWidget         *widget,
104                                            GdkEventClient    *event);
105
106
107 static GtkBinClass *parent_class = NULL;
108 static guint window_signals[LAST_SIGNAL] = { 0 };
109
110
111 GtkType
112 gtk_window_get_type (void)
113 {
114   static GtkType window_type = 0;
115
116   if (!window_type)
117     {
118       GtkTypeInfo window_info =
119       {
120         "GtkWindow",
121         sizeof (GtkWindow),
122         sizeof (GtkWindowClass),
123         (GtkClassInitFunc) gtk_window_class_init,
124         (GtkObjectInitFunc) gtk_window_init,
125         (GtkArgSetFunc) gtk_window_set_arg,
126         (GtkArgGetFunc) gtk_window_get_arg,
127       };
128
129       window_type = gtk_type_unique (gtk_bin_get_type (), &window_info);
130     }
131
132   return window_type;
133 }
134
135 static void
136 gtk_window_class_init (GtkWindowClass *klass)
137 {
138   GtkObjectClass *object_class;
139   GtkWidgetClass *widget_class;
140   GtkContainerClass *container_class;
141
142   object_class = (GtkObjectClass*) klass;
143   widget_class = (GtkWidgetClass*) klass;
144   container_class = (GtkContainerClass*) klass;
145
146   parent_class = gtk_type_class (gtk_bin_get_type ());
147
148   gtk_object_add_arg_type ("GtkWindow::type", GTK_TYPE_WINDOW_TYPE, GTK_ARG_READWRITE, ARG_TYPE);
149   gtk_object_add_arg_type ("GtkWindow::title", GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_TITLE);
150   gtk_object_add_arg_type ("GtkWindow::auto_shrink", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_AUTO_SHRINK);
151   gtk_object_add_arg_type ("GtkWindow::allow_shrink", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_ALLOW_SHRINK);
152   gtk_object_add_arg_type ("GtkWindow::allow_grow", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_ALLOW_GROW);
153   gtk_object_add_arg_type ("GtkWindow::window_position", GTK_TYPE_WINDOW_POSITION, GTK_ARG_READWRITE, ARG_WIN_POS);
154
155   window_signals[SET_FOCUS] =
156     gtk_signal_new ("set_focus",
157                     GTK_RUN_LAST,
158                     object_class->type,
159                     GTK_SIGNAL_OFFSET (GtkWindowClass, set_focus),
160                     gtk_window_marshal_signal_2,
161                     GTK_TYPE_NONE, 1,
162                     GTK_TYPE_POINTER);
163
164   gtk_object_class_add_signals (object_class, window_signals, LAST_SIGNAL);
165
166   object_class->shutdown = gtk_window_shutdown;
167   object_class->destroy = gtk_window_destroy;
168   object_class->finalize = gtk_window_finalize;
169
170   widget_class->show = gtk_window_show;
171   widget_class->hide = gtk_window_hide;
172   widget_class->map = gtk_window_map;
173   widget_class->unmap = gtk_window_unmap;
174   widget_class->realize = gtk_window_realize;
175   widget_class->size_request = gtk_window_size_request;
176   widget_class->size_allocate = gtk_window_size_allocate;
177   widget_class->expose_event = gtk_window_expose_event;
178   widget_class->configure_event = gtk_window_configure_event;
179   widget_class->key_press_event = gtk_window_key_press_event;
180   widget_class->key_release_event = gtk_window_key_release_event;
181   widget_class->enter_notify_event = gtk_window_enter_notify_event;
182   widget_class->leave_notify_event = gtk_window_leave_notify_event;
183   widget_class->focus_in_event = gtk_window_focus_in_event;
184   widget_class->focus_out_event = gtk_window_focus_out_event;
185   widget_class->client_event = gtk_window_client_event;
186
187   container_class->check_resize = gtk_window_check_resize;
188
189   klass->set_focus = gtk_real_window_set_focus;
190 }
191
192 static void
193 gtk_window_init (GtkWindow *window)
194 {
195   GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
196   GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
197
198   gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
199
200   window->title = NULL;
201   window->wmclass_name = g_strdup (gdk_progname);
202   window->wmclass_class = g_strdup (gdk_progclass);
203   window->type = GTK_WINDOW_TOPLEVEL;
204   window->focus_widget = NULL;
205   window->default_widget = NULL;
206   window->resize_count = 0;
207   window->allow_shrink = FALSE;
208   window->allow_grow = TRUE;
209   window->auto_shrink = FALSE;
210   window->handling_resize = FALSE;
211   window->position = GTK_WIN_POS_NONE;
212   window->use_uposition = TRUE;
213   
214   gtk_container_register_toplevel (GTK_CONTAINER (window));
215 }
216
217 static void
218 gtk_window_set_arg (GtkWindow  *window,
219                     GtkArg     *arg,
220                     guint       arg_id)
221 {
222   switch (arg_id)
223     {
224     case ARG_TYPE:
225       window->type = GTK_VALUE_ENUM (*arg);
226       break;
227     case ARG_TITLE:
228       gtk_window_set_title (window, GTK_VALUE_STRING (*arg));
229       break;
230     case ARG_AUTO_SHRINK:
231       window->auto_shrink = (GTK_VALUE_BOOL (*arg) != FALSE);
232       gtk_window_set_hints (GTK_WIDGET (window), &GTK_WIDGET (window)->requisition);
233       break;
234     case ARG_ALLOW_SHRINK:
235       window->allow_shrink = (GTK_VALUE_BOOL (*arg) != FALSE);
236       gtk_window_set_hints (GTK_WIDGET (window), &GTK_WIDGET (window)->requisition);
237       break;
238     case ARG_ALLOW_GROW:
239       window->allow_grow = (GTK_VALUE_BOOL (*arg) != FALSE);
240       gtk_window_set_hints (GTK_WIDGET (window), &GTK_WIDGET (window)->requisition);
241       break;
242     case ARG_WIN_POS:
243       gtk_window_position (window, GTK_VALUE_ENUM (*arg));
244       break;
245     default:
246       break;
247     }
248 }
249
250 static void
251 gtk_window_get_arg (GtkWindow  *window,
252                     GtkArg     *arg,
253                     guint       arg_id)
254 {
255   switch (arg_id)
256     {
257     case ARG_TYPE:
258       GTK_VALUE_ENUM (*arg) = window->type;
259       break;
260     case ARG_TITLE:
261       GTK_VALUE_STRING (*arg) = g_strdup (window->title);
262       break;
263     case ARG_AUTO_SHRINK:
264       GTK_VALUE_BOOL (*arg) = window->auto_shrink;
265       break;
266     case ARG_ALLOW_SHRINK:
267       GTK_VALUE_BOOL (*arg) = window->allow_shrink;
268       break;
269     case ARG_ALLOW_GROW:
270       GTK_VALUE_BOOL (*arg) = window->allow_grow;
271       break;
272     case ARG_WIN_POS:
273       GTK_VALUE_ENUM (*arg) = window->position;
274       break;
275     default:
276       arg->type = GTK_TYPE_INVALID;
277       break;
278     }
279 }
280
281 GtkWidget*
282 gtk_window_new (GtkWindowType type)
283 {
284   GtkWindow *window;
285
286   window = gtk_type_new (gtk_window_get_type ());
287
288   window->type = type;
289
290   return GTK_WIDGET (window);
291 }
292
293 void
294 gtk_window_set_title (GtkWindow   *window,
295                       const gchar *title)
296 {
297   g_return_if_fail (window != NULL);
298   g_return_if_fail (GTK_IS_WINDOW (window));
299
300   if (window->title)
301     g_free (window->title);
302   window->title = g_strdup (title);
303
304   if (GTK_WIDGET_REALIZED (window))
305     gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
306 }
307
308 void
309 gtk_window_set_wmclass (GtkWindow *window,
310                         const gchar *wmclass_name,
311                         const gchar *wmclass_class)
312 {
313   g_return_if_fail (window != NULL);
314   g_return_if_fail (GTK_IS_WINDOW (window));
315
316   g_free (window->wmclass_name);
317   window->wmclass_name = g_strdup (wmclass_name);
318
319   g_free (window->wmclass_class);
320   window->wmclass_class = g_strdup (wmclass_class);
321
322   if (GTK_WIDGET_REALIZED (window))
323     g_warning ("shouldn't set wmclass after window is realized!\n");
324 }
325
326 void
327 gtk_window_set_focus (GtkWindow *window,
328                       GtkWidget *focus)
329 {
330   gtk_signal_emit (GTK_OBJECT (window), window_signals[SET_FOCUS], focus);
331 }
332
333 void
334 gtk_window_set_default (GtkWindow *window,
335                         GtkWidget *default_widget)
336 {
337   g_return_if_fail (window != NULL);
338   g_return_if_fail (GTK_IS_WINDOW (window));
339
340   if (default_widget)
341     g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
342
343   if (window->default_widget != default_widget)
344     {
345       if (window->default_widget)
346         {
347           GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
348           gtk_widget_draw_default (window->default_widget);
349         }
350
351       window->default_widget = default_widget;
352
353       if (window->default_widget)
354         {
355           GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
356           gtk_widget_draw_default (window->default_widget);
357         }
358     }
359 }
360
361 void
362 gtk_window_set_policy (GtkWindow *window,
363                        gint       allow_shrink,
364                        gint       allow_grow,
365                        gint       auto_shrink)
366 {
367   g_return_if_fail (window != NULL);
368   g_return_if_fail (GTK_IS_WINDOW (window));
369
370   window->allow_shrink = (allow_shrink != FALSE);
371   window->allow_grow = (allow_grow != FALSE);
372   window->auto_shrink = (auto_shrink != FALSE);
373
374   gtk_window_set_hints (GTK_WIDGET (window), &GTK_WIDGET (window)->requisition);
375 }
376
377 void
378 gtk_window_add_accel_group (GtkWindow        *window,
379                             GtkAccelGroup    *accel_group)
380 {
381   g_return_if_fail (window != NULL);
382   g_return_if_fail (GTK_IS_WINDOW (window));
383   g_return_if_fail (accel_group != NULL);
384
385   gtk_accel_group_attach (accel_group, GTK_OBJECT (window));
386 }
387
388 void
389 gtk_window_remove_accel_group (GtkWindow       *window,
390                                GtkAccelGroup   *accel_group)
391 {
392   g_return_if_fail (window != NULL);
393   g_return_if_fail (GTK_IS_WINDOW (window));
394   g_return_if_fail (accel_group != NULL);
395
396   gtk_accel_group_detach (accel_group, GTK_OBJECT (window));
397 }
398
399 void
400 gtk_window_position (GtkWindow         *window,
401                      GtkWindowPosition  position)
402 {
403   g_return_if_fail (window != NULL);
404   g_return_if_fail (GTK_IS_WINDOW (window));
405
406   window->position = position;
407 }
408
409 gint
410 gtk_window_activate_focus (GtkWindow      *window)
411 {
412   g_return_val_if_fail (window != NULL, FALSE);
413   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
414
415   if (window->focus_widget)
416     {
417       gtk_widget_activate (window->focus_widget);
418       return TRUE;
419     }
420
421   return FALSE;
422 }
423
424 gint
425 gtk_window_activate_default (GtkWindow      *window)
426 {
427   g_return_val_if_fail (window != NULL, FALSE);
428   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
429
430   if (window->default_widget)
431     {
432       gtk_widget_activate (window->default_widget);
433       return TRUE;
434     }
435
436   return FALSE;
437 }
438
439 static void
440 gtk_window_marshal_signal_2 (GtkObject      *object,
441                              GtkSignalFunc   func,
442                              gpointer        func_data,
443                              GtkArg         *args)
444 {
445   GtkWindowSignal2 rfunc;
446
447   rfunc = (GtkWindowSignal2) func;
448
449   (* rfunc) (object, GTK_VALUE_POINTER (args[0]), func_data);
450 }
451
452 static void
453 gtk_window_shutdown (GtkObject *object)
454 {
455   GtkWindow *window;
456
457   g_return_if_fail (object != NULL);
458   g_return_if_fail (GTK_IS_WINDOW (object));
459
460   window = GTK_WINDOW (object);
461
462   gtk_window_set_focus (window, NULL);
463   gtk_window_set_default (window, NULL);
464
465   GTK_OBJECT_CLASS (parent_class)->shutdown (object);
466 }
467
468 static void
469 gtk_window_destroy (GtkObject *object)
470 {
471   g_return_if_fail (object != NULL);
472   g_return_if_fail (GTK_IS_WINDOW (object));
473
474   gtk_container_unregister_toplevel (GTK_CONTAINER (object));
475
476   GTK_OBJECT_CLASS (parent_class)->destroy (object);
477 }
478
479 static void
480 gtk_window_finalize (GtkObject *object)
481 {
482   GtkWindow *window;
483
484   g_return_if_fail (object != NULL);
485   g_return_if_fail (GTK_IS_WINDOW (object));
486
487   window = GTK_WINDOW (object);
488   g_free (window->title);
489   g_free (window->wmclass_name);
490   g_free (window->wmclass_class);
491
492   GTK_OBJECT_CLASS(parent_class)->finalize (object);
493 }
494
495 static void
496 gtk_window_show (GtkWidget *widget)
497 {
498   g_return_if_fail (widget != NULL);
499   g_return_if_fail (GTK_IS_WINDOW (widget));
500
501   GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
502   gtk_container_check_resize (GTK_CONTAINER (widget));
503   gtk_widget_map (widget);
504 }
505
506 static void
507 gtk_window_hide (GtkWidget *widget)
508 {
509   g_return_if_fail (widget != NULL);
510   g_return_if_fail (GTK_IS_WINDOW (widget));
511
512   GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
513   gtk_widget_unmap (widget);
514 }
515
516 static void
517 gtk_window_map (GtkWidget *widget)
518 {
519   GtkWindow *window;
520
521   g_return_if_fail (widget != NULL);
522   g_return_if_fail (GTK_IS_WINDOW (widget));
523
524   GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
525
526   window = GTK_WINDOW (widget);
527
528   if (window->bin.child &&
529       GTK_WIDGET_VISIBLE (window->bin.child) &&
530       !GTK_WIDGET_MAPPED (window->bin.child))
531     gtk_widget_map (window->bin.child);
532
533   gtk_window_set_hints (widget, &widget->requisition);
534   gdk_window_show (widget->window);
535 }
536
537 static void
538 gtk_window_unmap (GtkWidget *widget)
539 {
540   GtkWindow *window;
541
542   g_return_if_fail (widget != NULL);
543   g_return_if_fail (GTK_IS_WINDOW (widget));
544
545   GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
546   gdk_window_hide (widget->window);
547
548   window = GTK_WINDOW (widget);
549   window->use_uposition = TRUE;
550 }
551
552 static void
553 gtk_window_realize (GtkWidget *widget)
554 {
555   GtkWindow *window;
556   GdkWindowAttr attributes;
557   gint attributes_mask;
558
559   g_return_if_fail (widget != NULL);
560   g_return_if_fail (GTK_IS_WINDOW (widget));
561
562   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
563   window = GTK_WINDOW (widget);
564
565   switch (window->type)
566     {
567     case GTK_WINDOW_TOPLEVEL:
568       attributes.window_type = GDK_WINDOW_TOPLEVEL;
569       break;
570     case GTK_WINDOW_DIALOG:
571       attributes.window_type = GDK_WINDOW_DIALOG;
572       break;
573     case GTK_WINDOW_POPUP:
574       attributes.window_type = GDK_WINDOW_TEMP;
575       break;
576     }
577
578   attributes.title = window->title;
579   attributes.wmclass_name = window->wmclass_name;
580   attributes.wmclass_class = window->wmclass_class;
581   attributes.width = widget->allocation.width;
582   attributes.height = widget->allocation.height;
583   attributes.wclass = GDK_INPUT_OUTPUT;
584   attributes.visual = gtk_widget_get_visual (widget);
585   attributes.colormap = gtk_widget_get_colormap (widget);
586   attributes.event_mask = gtk_widget_get_events (widget);
587   attributes.event_mask |= (GDK_EXPOSURE_MASK |
588                             GDK_KEY_PRESS_MASK |
589                             GDK_ENTER_NOTIFY_MASK |
590                             GDK_LEAVE_NOTIFY_MASK |
591                             GDK_FOCUS_CHANGE_MASK |
592                             GDK_STRUCTURE_MASK);
593
594   attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
595   attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
596   attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
597
598   widget->window = gdk_window_new (NULL, &attributes, attributes_mask);
599   gdk_window_set_user_data (widget->window, window);
600
601   widget->style = gtk_style_attach (widget->style, widget->window);
602   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
603 }
604
605 static void
606 gtk_window_size_request (GtkWidget      *widget,
607                          GtkRequisition *requisition)
608 {
609   GtkWindow *window;
610
611   g_return_if_fail (widget != NULL);
612   g_return_if_fail (GTK_IS_WINDOW (widget));
613   g_return_if_fail (requisition != NULL);
614
615   window = GTK_WINDOW (widget);
616
617   if (window->bin.child)
618     {
619       requisition->width = GTK_CONTAINER (window)->border_width * 2;
620       requisition->height = GTK_CONTAINER (window)->border_width * 2;
621
622       gtk_widget_size_request (window->bin.child, &window->bin.child->requisition);
623
624       requisition->width += window->bin.child->requisition.width;
625       requisition->height += window->bin.child->requisition.height;
626     }
627   else
628     {
629       if (!GTK_WIDGET_VISIBLE (window))
630         GTK_CONTAINER (window)->need_resize = TRUE;
631     }
632 }
633
634 static void
635 gtk_window_size_allocate (GtkWidget     *widget,
636                           GtkAllocation *allocation)
637 {
638   GtkWindow *window;
639   GtkAllocation child_allocation;
640
641   g_return_if_fail (widget != NULL);
642   g_return_if_fail (GTK_IS_WINDOW (widget));
643   g_return_if_fail (allocation != NULL);
644
645   window = GTK_WINDOW (widget);
646   widget->allocation = *allocation;
647
648   if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
649     {
650       child_allocation.x = GTK_CONTAINER (window)->border_width;
651       child_allocation.y = GTK_CONTAINER (window)->border_width;
652       child_allocation.width = allocation->width - child_allocation.x * 2;
653       child_allocation.height = allocation->height - child_allocation.y * 2;
654
655       gtk_widget_size_allocate (window->bin.child, &child_allocation);
656     }
657 }
658
659 static gint
660 gtk_window_expose_event (GtkWidget      *widget,
661                          GdkEventExpose *event)
662 {
663   g_return_val_if_fail (widget != NULL, FALSE);
664   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
665   g_return_val_if_fail (event != NULL, FALSE);
666
667   if (GTK_WIDGET_DRAWABLE (widget))
668     if (GTK_WIDGET_CLASS (parent_class)->expose_event)
669       return (* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event);
670   
671   return FALSE;
672 }
673
674 static gint
675 gtk_window_configure_event (GtkWidget         *widget,
676                             GdkEventConfigure *event)
677 {
678   GtkWindow *window;
679   GtkAllocation allocation;
680   
681   g_return_val_if_fail (widget != NULL, FALSE);
682   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
683   g_return_val_if_fail (event != NULL, FALSE);
684   
685   window = GTK_WINDOW (widget);
686
687   /* If the window was merely moved, do nothing */
688   if ((widget->allocation.width == event->width) &&
689       (widget->allocation.height == event->height) &&
690       (window->resize_count == 0))
691     return FALSE;
692   
693   window->handling_resize = TRUE;
694   
695   allocation.x = 0;
696   allocation.y = 0;
697   allocation.width = event->width;
698   allocation.height = event->height;
699   
700   gtk_widget_size_allocate (widget, &allocation);
701   
702   if (window->bin.child &&
703       GTK_WIDGET_VISIBLE (window->bin.child) &&
704       !GTK_WIDGET_MAPPED (window->bin.child))
705     gtk_widget_map (window->bin.child);
706   
707   if (window->resize_count > 0)
708       window->resize_count -= 1;
709   
710   window->handling_resize = FALSE;
711   
712   return FALSE;
713 }
714
715 static gint
716 gtk_window_key_press_event (GtkWidget   *widget,
717                             GdkEventKey *event)
718 {
719   GtkWindow *window;
720   GtkDirectionType direction = 0;
721   gboolean handled;
722
723   g_return_val_if_fail (widget != NULL, FALSE);
724   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
725   g_return_val_if_fail (event != NULL, FALSE);
726
727   window = GTK_WINDOW (widget);
728
729   handled = FALSE;
730   
731   if (window->focus_widget)
732     {
733       handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
734     }
735     
736   if (!handled)
737     handled = gtk_accel_groups_activate (GTK_OBJECT (window), event->keyval, event->state);
738
739   if (!handled)
740     {
741       switch (event->keyval)
742         {
743         case GDK_space:
744           if (window->focus_widget)
745             {
746               gtk_widget_activate (window->focus_widget);
747               handled = TRUE;
748             }
749           break;
750         case GDK_Return:
751         case GDK_KP_Enter:
752           if (window->default_widget)
753             {
754               gtk_widget_activate (window->default_widget);
755               handled = TRUE;
756             }
757           else if (window->focus_widget)
758             {
759               gtk_widget_activate (window->focus_widget);
760               handled = TRUE;
761             }
762           break;
763         case GDK_Up:
764         case GDK_Down:
765         case GDK_Left:
766         case GDK_Right:
767         case GDK_Tab:
768         case GDK_ISO_Left_Tab:
769           switch (event->keyval)
770             {
771             case GDK_Up:
772               direction = GTK_DIR_UP;
773               break;
774             case GDK_Down:
775               direction = GTK_DIR_DOWN;
776               break;
777             case GDK_Left:
778               direction = GTK_DIR_LEFT;
779               break;
780             case GDK_Right:
781               direction = GTK_DIR_RIGHT;
782               break;
783             case GDK_Tab:
784             case GDK_ISO_Left_Tab:
785               if (event->state & GDK_SHIFT_MASK)
786                 direction = GTK_DIR_TAB_BACKWARD;
787               else
788                 direction = GTK_DIR_TAB_FORWARD;
789               break;
790             default :
791               direction = GTK_DIR_UP; /* never reached, but makes compiler happy */
792             }
793
794           gtk_container_focus (GTK_CONTAINER (widget), direction);
795
796           if (!GTK_CONTAINER (window)->focus_child)
797             gtk_window_set_focus (GTK_WINDOW (widget), NULL);
798           else
799             handled = TRUE;
800           break;
801         }
802     }
803
804   if (!handled && GTK_WIDGET_CLASS (parent_class)->key_press_event)
805     handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
806
807   return handled;
808 }
809
810 static gint
811 gtk_window_key_release_event (GtkWidget   *widget,
812                               GdkEventKey *event)
813 {
814   GtkWindow *window;
815   gint handled;
816   
817   g_return_val_if_fail (widget != NULL, FALSE);
818   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
819   g_return_val_if_fail (event != NULL, FALSE);
820   
821   window = GTK_WINDOW (widget);
822   handled = FALSE;
823   if (window->focus_widget)
824     {
825       handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
826     }
827
828   if (!handled && GTK_WIDGET_CLASS (parent_class)->key_release_event)
829     handled = GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
830
831   return handled;
832 }
833
834 static gint
835 gtk_window_enter_notify_event (GtkWidget        *widget,
836                                GdkEventCrossing *event)
837 {
838   g_return_val_if_fail (widget != NULL, FALSE);
839   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
840   g_return_val_if_fail (event != NULL, FALSE);
841
842   return FALSE;
843 }
844
845 static gint
846 gtk_window_leave_notify_event (GtkWidget        *widget,
847                                GdkEventCrossing *event)
848 {
849   g_return_val_if_fail (widget != NULL, FALSE);
850   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
851   g_return_val_if_fail (event != NULL, FALSE);
852
853   return FALSE;
854 }
855
856 static gint
857 gtk_window_focus_in_event (GtkWidget     *widget,
858                            GdkEventFocus *event)
859 {
860   GtkWindow *window;
861   GdkEventFocus fevent;
862
863   g_return_val_if_fail (widget != NULL, FALSE);
864   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
865   g_return_val_if_fail (event != NULL, FALSE);
866
867   /* It appears spurious focus in events can occur when
868    *  the window is hidden. So we'll just check to see if
869    *  the window is visible before actually handling the
870    *  event
871    */
872   if (GTK_WIDGET_VISIBLE (widget))
873     {
874       window = GTK_WINDOW (widget);
875       if (window->focus_widget && !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
876         {
877           fevent.type = GDK_FOCUS_CHANGE;
878           fevent.window = window->focus_widget->window;
879           fevent.in = TRUE;
880
881           gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
882         }
883     }
884
885   return FALSE;
886 }
887
888 static gint
889 gtk_window_focus_out_event (GtkWidget     *widget,
890                             GdkEventFocus *event)
891 {
892   GtkWindow *window;
893   GdkEventFocus fevent;
894
895   g_return_val_if_fail (widget != NULL, FALSE);
896   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
897   g_return_val_if_fail (event != NULL, FALSE);
898
899   window = GTK_WINDOW (widget);
900   if (window->focus_widget && GTK_WIDGET_HAS_FOCUS (window->focus_widget))
901     {
902       fevent.type = GDK_FOCUS_CHANGE;
903       fevent.window = window->focus_widget->window;
904       fevent.in = FALSE;
905
906       gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
907     }
908
909   return FALSE;
910 }
911
912 static void
913 gtk_window_read_rcfiles (GtkWidget *widget,
914                          GdkEventClient *event)
915 {
916   GList *toplevels;
917   
918   if (gtk_rc_reparse_all ())
919     {
920       toplevels = gdk_window_get_toplevels();
921       while (toplevels)
922         {
923           GtkWidget *widget;
924           gdk_window_get_user_data (toplevels->data, (gpointer *)&widget);
925           
926           if (widget)
927             gtk_widget_reset_rc_styles (widget);
928           
929           toplevels = toplevels->next;
930         }
931       g_list_free (toplevels);
932     }
933 }
934
935 static gint
936 gtk_window_client_event (GtkWidget      *widget,
937                          GdkEventClient *event)
938 {
939   static GdkAtom atom_rcfiles = GDK_NONE;
940   g_return_val_if_fail (widget != NULL, FALSE);
941   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
942   g_return_val_if_fail (event != NULL, FALSE);
943
944   if (!atom_rcfiles)
945     atom_rcfiles = gdk_atom_intern("_GTK_READ_RCFILES", FALSE);
946
947   if(event->message_type == atom_rcfiles) 
948     gtk_window_read_rcfiles (widget, event);    
949
950   return FALSE;
951 }
952
953 static void
954 gtk_window_check_resize (GtkContainer *container)
955 {
956   GtkWindow *window;
957
958   g_return_if_fail (container != NULL);
959   g_return_if_fail (GTK_IS_WINDOW (container));
960
961   window = GTK_WINDOW (container);
962   if (!window->handling_resize)
963     {
964       if (GTK_WIDGET_VISIBLE (container))
965         gtk_window_move_resize (window);
966       else
967         GTK_CONTAINER (window)->need_resize = TRUE;
968     }
969 }
970
971 /* FIXME: we leave container->resize_widgets set under some
972    circumstances ? */
973 static void
974 gtk_window_move_resize (GtkWindow *window)
975 {
976   GtkWidget    *widget;
977   GtkContainer *container;
978   gint x, y;
979   gint width, height;
980   gint screen_width;
981   gint screen_height;
982   gboolean needed_resize;
983
984   g_return_if_fail (window != NULL);
985   g_return_if_fail (GTK_IS_WINDOW (window));
986
987   widget = GTK_WIDGET (window);
988   container = GTK_CONTAINER (widget);
989
990   /* Remember old size, to know if we have to reset hints */
991   width = widget->requisition.width;
992   height = widget->requisition.height;
993   gtk_widget_size_request (widget, &widget->requisition);
994
995   if ((width != widget->requisition.width ||
996        height != widget->requisition.height))
997     {
998       gboolean saved_use_upos;
999
1000       saved_use_upos = window->use_uposition;
1001       gtk_window_set_hints (widget, &widget->requisition);
1002       window->use_uposition = saved_use_upos;
1003     }
1004   
1005   x = -1;
1006   y = -1;
1007   width = widget->requisition.width;
1008   height = widget->requisition.height;
1009   
1010   if (window->use_uposition)
1011     switch (window->position)
1012       {
1013       case GTK_WIN_POS_CENTER:
1014         x = (gdk_screen_width () - width) / 2;
1015         y = (gdk_screen_height () - height) / 2;
1016         gtk_widget_set_uposition (widget, x, y);
1017         break;
1018       case GTK_WIN_POS_MOUSE:
1019         gdk_window_get_pointer (NULL, &x, &y, NULL);
1020         
1021         x -= width / 2;
1022         y -= height / 2;
1023         
1024         screen_width = gdk_screen_width ();
1025         screen_height = gdk_screen_height ();
1026         
1027         if (x < 0)
1028           x = 0;
1029         else if (x > (screen_width - width))
1030           x = screen_width - width;
1031         
1032         if (y < 0)
1033           y = 0;
1034         else if (y > (screen_height - height))
1035           y = screen_height - height;
1036         
1037         gtk_widget_set_uposition (widget, x, y);
1038         break;
1039       }
1040
1041   /* Now, do the resizing */
1042
1043   needed_resize = container->need_resize;
1044   container->need_resize = FALSE;
1045
1046   if ((widget->requisition.width == 0) ||
1047       (widget->requisition.height == 0))
1048     {
1049       widget->requisition.width = 200;
1050       widget->requisition.height = 200;
1051     }
1052   
1053   if (!GTK_WIDGET_REALIZED (window))
1054     {
1055       GtkAllocation allocation;
1056
1057       allocation.x = 0;
1058       allocation.y = 0;
1059       allocation.width = widget->requisition.width;
1060       allocation.height = widget->requisition.height;
1061       
1062       gtk_widget_size_allocate (widget, &allocation);
1063
1064       return;
1065     }
1066   
1067   gdk_window_get_geometry (widget->window, NULL, NULL, &width, &height, NULL);
1068   
1069   if ((window->auto_shrink &&
1070        ((width != widget->requisition.width) ||
1071         (height != widget->requisition.height))) ||
1072       (width < widget->requisition.width) ||
1073       (height < widget->requisition.height))
1074     {
1075       window->resize_count += 1;
1076       if ((x != -1) && (y != -1))
1077         gdk_window_move_resize (widget->window, x, y,
1078                                 widget->requisition.width,
1079                                 widget->requisition.height);
1080       else
1081         gdk_window_resize (widget->window,
1082                            widget->requisition.width,
1083                            widget->requisition.height);
1084     }
1085   else if (needed_resize)
1086     {
1087       /* The windows contents changed size while it was not
1088        * visible, so reallocate everything, since we didn't
1089        * keep track of what changed
1090        */
1091       GtkAllocation allocation;
1092
1093       allocation.x = 0;
1094       allocation.y = 0;
1095       allocation.width = widget->requisition.width;
1096       allocation.height = widget->requisition.height;
1097       
1098       gtk_widget_size_allocate (widget, &allocation);
1099     }
1100   else
1101     {
1102       if ((x != -1) && (y != -1))
1103         gdk_window_move (widget->window, x, y);
1104
1105       gtk_container_resize_children (GTK_CONTAINER (window));
1106     }
1107 }
1108
1109 static void
1110 gtk_real_window_set_focus (GtkWindow *window,
1111                            GtkWidget *focus)
1112 {
1113   GdkEventFocus event;
1114
1115   g_return_if_fail (window != NULL);
1116   g_return_if_fail (GTK_IS_WINDOW (window));
1117
1118   if (focus && !GTK_WIDGET_CAN_FOCUS (focus))
1119     return;
1120
1121   if (window->focus_widget != focus)
1122     {
1123       if (window->focus_widget)
1124         {
1125           event.type = GDK_FOCUS_CHANGE;
1126           event.window = window->focus_widget->window;
1127           event.in = FALSE;
1128
1129           gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
1130         }
1131
1132       window->focus_widget = focus;
1133
1134       if (window->focus_widget)
1135         {
1136           event.type = GDK_FOCUS_CHANGE;
1137           event.window = window->focus_widget->window;
1138           event.in = TRUE;
1139
1140           gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
1141         }
1142     }
1143 }
1144
1145 static void
1146 gtk_window_set_hints (GtkWidget      *widget,
1147                       GtkRequisition *requisition)
1148 {
1149   GtkWindow *window;
1150   GtkWidgetAuxInfo *aux_info;
1151   gint flags;
1152   gint ux, uy;
1153
1154   g_return_if_fail (widget != NULL);
1155   g_return_if_fail (GTK_IS_WINDOW (widget));
1156   g_return_if_fail (requisition != NULL);
1157
1158   if (GTK_WIDGET_REALIZED (widget))
1159     {
1160       window = GTK_WINDOW (widget);
1161
1162       flags = 0;
1163       ux = 0;
1164       uy = 0;
1165
1166       aux_info = gtk_object_get_data (GTK_OBJECT (widget), "gtk-aux-info");
1167       if (aux_info && (aux_info->x != -1) && (aux_info->y != -1))
1168         {
1169           ux = aux_info->x;
1170           uy = aux_info->y;
1171           flags |= GDK_HINT_POS;
1172         }
1173
1174       if (!window->allow_shrink)
1175         flags |= GDK_HINT_MIN_SIZE;
1176       if (!window->allow_grow)
1177         flags |= GDK_HINT_MAX_SIZE;
1178
1179       gdk_window_set_hints (widget->window, ux, uy,
1180                             requisition->width, requisition->height,
1181                             requisition->width, requisition->height,
1182                             flags);
1183
1184       if (window->use_uposition && (flags & GDK_HINT_POS))
1185         {
1186           window->use_uposition = FALSE;
1187           gdk_window_move (widget->window, ux, uy);
1188         }
1189     }
1190 }