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