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