]> Pileus Git - ~andy/gtk/blob - gtk/gtkwindow.c
changed scrolled window inheritance, it inherits from GtkBin now.
[~andy/gtk] / gtk / gtkwindow.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19 #include <string.h>
20 #include <limits.h>
21 #include "gdk/gdk.h"
22 #include "gdk/gdkkeysyms.h"
23 #include "gdk/gdkx.h"
24 #include "gtkprivate.h"
25 #include "gtkrc.h"
26 #include "gtksignal.h"
27 #include "gtkwindow.h"
28 #include "gtkbindings.h"
29 #include "gtkmain.h"
30
31 enum {
32   SET_FOCUS,
33   LAST_SIGNAL
34 };
35 enum {
36   ARG_0,
37   ARG_TYPE,
38   ARG_TITLE,
39   ARG_AUTO_SHRINK,
40   ARG_ALLOW_SHRINK,
41   ARG_ALLOW_GROW,
42   ARG_WIN_POS
43 };
44
45 static void gtk_window_class_init         (GtkWindowClass    *klass);
46 static void gtk_window_init               (GtkWindow         *window);
47 static void gtk_window_set_arg            (GtkObject         *object,
48                                            GtkArg            *arg,
49                                            guint              arg_id);
50 static void gtk_window_get_arg            (GtkObject         *object,
51                                            GtkArg            *arg,
52                                            guint              arg_id);
53 static void gtk_window_shutdown           (GtkObject         *object);
54 static void gtk_window_destroy            (GtkObject         *object);
55 static void gtk_window_finalize           (GtkObject         *object);
56 static void gtk_window_show               (GtkWidget         *widget);
57 static void gtk_window_hide               (GtkWidget         *widget);
58 static void gtk_window_map                (GtkWidget         *widget);
59 static void gtk_window_unmap              (GtkWidget         *widget);
60 static void gtk_window_realize            (GtkWidget         *widget);
61 static void gtk_window_size_request       (GtkWidget         *widget,
62                                            GtkRequisition    *requisition);
63 static void gtk_window_size_allocate      (GtkWidget         *widget,
64                                            GtkAllocation     *allocation);
65 static gint gtk_window_expose_event       (GtkWidget         *widget,
66                                            GdkEventExpose    *event);
67 static gint gtk_window_configure_event    (GtkWidget         *widget,
68                                            GdkEventConfigure *event);
69 static gint gtk_window_key_press_event    (GtkWidget         *widget,
70                                            GdkEventKey       *event);
71 static gint gtk_window_key_release_event  (GtkWidget         *widget,
72                                            GdkEventKey       *event);
73 static gint gtk_window_enter_notify_event (GtkWidget         *widget,
74                                            GdkEventCrossing  *event);
75 static gint gtk_window_leave_notify_event (GtkWidget         *widget,
76                                            GdkEventCrossing  *event);
77 static gint gtk_window_focus_in_event     (GtkWidget         *widget,
78                                            GdkEventFocus     *event);
79 static gint gtk_window_focus_out_event    (GtkWidget         *widget,
80                                            GdkEventFocus     *event);
81 static gint gtk_window_client_event       (GtkWidget         *widget,
82                                            GdkEventClient    *event);
83 static void gtk_window_check_resize       (GtkContainer      *container);
84 static void gtk_real_window_set_focus     (GtkWindow         *window,
85                                            GtkWidget         *focus);
86 static void gtk_window_move_resize        (GtkWindow         *window);
87 static void gtk_window_set_hints          (GtkWidget         *widget,
88                                            GtkRequisition    *requisition);
89
90 static void gtk_window_read_rcfiles       (GtkWidget         *widget,
91                                            GdkEventClient    *event);
92 static void gtk_window_draw               (GtkWidget         *widget,
93                                            GdkRectangle      *area);
94 static void gtk_window_paint              (GtkWidget         *widget,
95                                            GdkRectangle      *area);
96 static gint gtk_window_expose             (GtkWidget         *widget,
97                                            GdkEventExpose    *event);
98 static void gtk_window_style_set          (GtkWidget         *widget,
99                                            GtkStyle          *previous_style);
100
101 static GtkBinClass *parent_class = NULL;
102 static guint window_signals[LAST_SIGNAL] = { 0 };
103
104
105 GtkType
106 gtk_window_get_type (void)
107 {
108   static GtkType window_type = 0;
109
110   if (!window_type)
111     {
112       GtkTypeInfo window_info =
113       {
114         "GtkWindow",
115         sizeof (GtkWindow),
116         sizeof (GtkWindowClass),
117         (GtkClassInitFunc) gtk_window_class_init,
118         (GtkObjectInitFunc) gtk_window_init,
119         /* reserved_1 */ NULL,
120         /* reserved_2 */ NULL,
121         (GtkClassInitFunc) NULL,
122       };
123
124       window_type = gtk_type_unique (gtk_bin_get_type (), &window_info);
125     }
126
127   return window_type;
128 }
129
130 static void
131 gtk_window_class_init (GtkWindowClass *klass)
132 {
133   GtkObjectClass *object_class;
134   GtkWidgetClass *widget_class;
135   GtkContainerClass *container_class;
136
137   object_class = (GtkObjectClass*) klass;
138   widget_class = (GtkWidgetClass*) klass;
139   container_class = (GtkContainerClass*) klass;
140
141   parent_class = gtk_type_class (gtk_bin_get_type ());
142
143   gtk_object_add_arg_type ("GtkWindow::type", GTK_TYPE_WINDOW_TYPE, GTK_ARG_READWRITE, ARG_TYPE);
144   gtk_object_add_arg_type ("GtkWindow::title", GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_TITLE);
145   gtk_object_add_arg_type ("GtkWindow::auto_shrink", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_AUTO_SHRINK);
146   gtk_object_add_arg_type ("GtkWindow::allow_shrink", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_ALLOW_SHRINK);
147   gtk_object_add_arg_type ("GtkWindow::allow_grow", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_ALLOW_GROW);
148   gtk_object_add_arg_type ("GtkWindow::window_position", GTK_TYPE_WINDOW_POSITION, GTK_ARG_READWRITE, ARG_WIN_POS);
149
150   window_signals[SET_FOCUS] =
151     gtk_signal_new ("set_focus",
152                     GTK_RUN_LAST,
153                     object_class->type,
154                     GTK_SIGNAL_OFFSET (GtkWindowClass, set_focus),
155                     gtk_marshal_NONE__POINTER,
156                     GTK_TYPE_NONE, 1,
157                     GTK_TYPE_POINTER);
158
159   gtk_object_class_add_signals (object_class, window_signals, LAST_SIGNAL);
160
161   object_class->set_arg = gtk_window_set_arg;
162   object_class->get_arg = gtk_window_get_arg;
163   object_class->shutdown = gtk_window_shutdown;
164   object_class->destroy = gtk_window_destroy;
165   object_class->finalize = gtk_window_finalize;
166
167   widget_class->show = gtk_window_show;
168   widget_class->hide = gtk_window_hide;
169   widget_class->map = gtk_window_map;
170   widget_class->unmap = gtk_window_unmap;
171   widget_class->realize = gtk_window_realize;
172   widget_class->size_request = gtk_window_size_request;
173   widget_class->size_allocate = gtk_window_size_allocate;
174   widget_class->expose_event = gtk_window_expose_event;
175   widget_class->configure_event = gtk_window_configure_event;
176   widget_class->key_press_event = gtk_window_key_press_event;
177   widget_class->key_release_event = gtk_window_key_release_event;
178   widget_class->enter_notify_event = gtk_window_enter_notify_event;
179   widget_class->leave_notify_event = gtk_window_leave_notify_event;
180   widget_class->focus_in_event = gtk_window_focus_in_event;
181   widget_class->focus_out_event = gtk_window_focus_out_event;
182   widget_class->client_event = gtk_window_client_event;
183   widget_class->style_set = gtk_window_style_set;
184
185   widget_class->draw = gtk_window_draw;
186   widget_class->expose_event = gtk_window_expose;
187    
188   container_class->check_resize = gtk_window_check_resize;
189
190   klass->set_focus = gtk_real_window_set_focus;
191 }
192
193 static void
194 gtk_window_init (GtkWindow *window)
195 {
196   GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
197   GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
198
199   gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
200
201   window->title = NULL;
202   window->wmclass_name = g_strdup (g_get_prgname ());
203   window->wmclass_class = g_strdup (gdk_progclass);
204   window->type = GTK_WINDOW_TOPLEVEL;
205   window->focus_widget = NULL;
206   window->default_widget = NULL;
207   window->resize_count = 0;
208   window->allow_shrink = FALSE;
209   window->allow_grow = TRUE;
210   window->auto_shrink = FALSE;
211   window->handling_resize = FALSE;
212   window->position = GTK_WIN_POS_NONE;
213   window->use_uposition = TRUE;
214   window->modal = FALSE;
215   
216   gtk_container_register_toplevel (GTK_CONTAINER (window));
217 }
218
219 static void
220 gtk_window_set_arg (GtkObject  *object,
221                     GtkArg     *arg,
222                     guint       arg_id)
223 {
224   GtkWindow  *window;
225
226   window = GTK_WINDOW (object);
227
228   switch (arg_id)
229     {
230     case ARG_TYPE:
231       window->type = GTK_VALUE_ENUM (*arg);
232       break;
233     case ARG_TITLE:
234       gtk_window_set_title (window, GTK_VALUE_STRING (*arg));
235       break;
236     case ARG_AUTO_SHRINK:
237       window->auto_shrink = (GTK_VALUE_BOOL (*arg) != FALSE);
238       gtk_window_set_hints (GTK_WIDGET (window), &GTK_WIDGET (window)->requisition);
239       break;
240     case ARG_ALLOW_SHRINK:
241       window->allow_shrink = (GTK_VALUE_BOOL (*arg) != FALSE);
242       gtk_window_set_hints (GTK_WIDGET (window), &GTK_WIDGET (window)->requisition);
243       break;
244     case ARG_ALLOW_GROW:
245       window->allow_grow = (GTK_VALUE_BOOL (*arg) != FALSE);
246       gtk_window_set_hints (GTK_WIDGET (window), &GTK_WIDGET (window)->requisition);
247       break;
248     case ARG_WIN_POS:
249       gtk_window_set_position (window, GTK_VALUE_ENUM (*arg));
250       break;
251     default:
252       break;
253     }
254 }
255
256 static void
257 gtk_window_get_arg (GtkObject  *object,
258                     GtkArg     *arg,
259                     guint       arg_id)
260 {
261   GtkWindow  *window;
262
263   window = GTK_WINDOW (object);
264
265   switch (arg_id)
266     {
267     case ARG_TYPE:
268       GTK_VALUE_ENUM (*arg) = window->type;
269       break;
270     case ARG_TITLE:
271       GTK_VALUE_STRING (*arg) = g_strdup (window->title);
272       break;
273     case ARG_AUTO_SHRINK:
274       GTK_VALUE_BOOL (*arg) = window->auto_shrink;
275       break;
276     case ARG_ALLOW_SHRINK:
277       GTK_VALUE_BOOL (*arg) = window->allow_shrink;
278       break;
279     case ARG_ALLOW_GROW:
280       GTK_VALUE_BOOL (*arg) = window->allow_grow;
281       break;
282     case ARG_WIN_POS:
283       GTK_VALUE_ENUM (*arg) = window->position;
284       break;
285     default:
286       arg->type = GTK_TYPE_INVALID;
287       break;
288     }
289 }
290
291 GtkWidget*
292 gtk_window_new (GtkWindowType type)
293 {
294   GtkWindow *window;
295
296   window = gtk_type_new (gtk_window_get_type ());
297
298   window->type = type;
299
300   return GTK_WIDGET (window);
301 }
302
303 void
304 gtk_window_set_title (GtkWindow   *window,
305                       const gchar *title)
306 {
307   g_return_if_fail (window != NULL);
308   g_return_if_fail (GTK_IS_WINDOW (window));
309
310   if (window->title)
311     g_free (window->title);
312   window->title = g_strdup (title);
313
314   if (GTK_WIDGET_REALIZED (window))
315     gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
316 }
317
318 void
319 gtk_window_set_wmclass (GtkWindow *window,
320                         const gchar *wmclass_name,
321                         const gchar *wmclass_class)
322 {
323   g_return_if_fail (window != NULL);
324   g_return_if_fail (GTK_IS_WINDOW (window));
325
326   g_free (window->wmclass_name);
327   window->wmclass_name = g_strdup (wmclass_name);
328
329   g_free (window->wmclass_class);
330   window->wmclass_class = g_strdup (wmclass_class);
331
332   if (GTK_WIDGET_REALIZED (window))
333     g_warning ("shouldn't set wmclass after window is realized!\n");
334 }
335
336 void
337 gtk_window_set_focus (GtkWindow *window,
338                       GtkWidget *focus)
339 {
340   gtk_signal_emit (GTK_OBJECT (window), window_signals[SET_FOCUS], focus);
341 }
342
343 void
344 gtk_window_set_default (GtkWindow *window,
345                         GtkWidget *default_widget)
346 {
347   g_return_if_fail (window != NULL);
348   g_return_if_fail (GTK_IS_WINDOW (window));
349
350   if (default_widget)
351     g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
352
353   if (window->default_widget != default_widget)
354     {
355       if (window->default_widget)
356         {
357           GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
358           gtk_widget_draw_default (window->default_widget);
359         }
360
361       window->default_widget = default_widget;
362
363       if (window->default_widget)
364         {
365           GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
366           gtk_widget_draw_default (window->default_widget);
367         }
368     }
369 }
370
371 void
372 gtk_window_set_policy (GtkWindow *window,
373                        gint       allow_shrink,
374                        gint       allow_grow,
375                        gint       auto_shrink)
376 {
377   g_return_if_fail (window != NULL);
378   g_return_if_fail (GTK_IS_WINDOW (window));
379
380   window->allow_shrink = (allow_shrink != FALSE);
381   window->allow_grow = (allow_grow != FALSE);
382   window->auto_shrink = (auto_shrink != FALSE);
383
384   gtk_window_set_hints (GTK_WIDGET (window), &GTK_WIDGET (window)->requisition);
385 }
386
387 void
388 gtk_window_add_accel_group (GtkWindow        *window,
389                             GtkAccelGroup    *accel_group)
390 {
391   g_return_if_fail (window != NULL);
392   g_return_if_fail (GTK_IS_WINDOW (window));
393   g_return_if_fail (accel_group != NULL);
394
395   gtk_accel_group_attach (accel_group, GTK_OBJECT (window));
396 }
397
398 void
399 gtk_window_remove_accel_group (GtkWindow       *window,
400                                GtkAccelGroup   *accel_group)
401 {
402   g_return_if_fail (window != NULL);
403   g_return_if_fail (GTK_IS_WINDOW (window));
404   g_return_if_fail (accel_group != NULL);
405
406   gtk_accel_group_detach (accel_group, GTK_OBJECT (window));
407 }
408
409 void
410 gtk_window_set_position (GtkWindow         *window,
411                          GtkWindowPosition  position)
412 {
413   g_return_if_fail (window != NULL);
414   g_return_if_fail (GTK_IS_WINDOW (window));
415
416   window->position = position;
417 }
418
419 gint
420 gtk_window_activate_focus (GtkWindow      *window)
421 {
422   g_return_val_if_fail (window != NULL, FALSE);
423   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
424
425   if (window->focus_widget)
426     {
427       gtk_widget_activate (window->focus_widget);
428       return TRUE;
429     }
430
431   return FALSE;
432 }
433
434 gint
435 gtk_window_activate_default (GtkWindow      *window)
436 {
437   g_return_val_if_fail (window != NULL, FALSE);
438   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
439
440   if (window->default_widget)
441     {
442       gtk_widget_activate (window->default_widget);
443       return TRUE;
444     }
445
446   return FALSE;
447 }
448
449 void
450 gtk_window_set_modal (GtkWindow *window, gboolean modal)
451 {
452   g_return_if_fail (window != NULL);
453   g_return_if_fail (GTK_IS_WINDOW (window));
454
455   /* If the widget was showed already, adjust it's grab state */
456   if (GTK_WIDGET_VISIBLE(GTK_WIDGET(window)))
457     {
458       if (window->modal && !modal)
459         gtk_grab_remove (GTK_WIDGET(window));
460       else if (!window->modal && modal)
461         gtk_grab_add (GTK_WIDGET(window));
462     }
463   
464   window->modal = modal;
465 }
466
467 void
468 gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
469 {
470   GList *embedded_windows;
471
472   g_return_if_fail (window != NULL);
473   g_return_if_fail (GTK_IS_WINDOW (window));
474   
475   g_print ("add %#x\n", xid);
476
477   embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
478   if (embedded_windows)
479     gtk_object_remove_no_notify_by_id (GTK_OBJECT (window), 
480                                        g_quark_from_static_string ("gtk-embedded"));
481   embedded_windows = g_list_prepend (embedded_windows,
482                                      GUINT_TO_POINTER (xid));
483
484   gtk_object_set_data_full (GTK_OBJECT (window), "gtk-embedded", 
485                             embedded_windows,
486                             embedded_windows ?
487                               (GtkDestroyNotify) g_list_free : NULL);
488 }
489
490 void
491 gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
492 {
493   GList *embedded_windows;
494   GList *node;
495
496   g_return_if_fail (window != NULL);
497   g_return_if_fail (GTK_IS_WINDOW (window));
498   
499   g_print ("remove %#x\n", xid);
500
501   embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
502   if (embedded_windows)
503     gtk_object_remove_no_notify_by_id (GTK_OBJECT (window), 
504                                        g_quark_from_static_string ("gtk-embedded"));
505
506   node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
507   if (node)
508     {
509       embedded_windows = g_list_remove_link (embedded_windows, node);
510       g_list_free_1 (node);
511     }
512   
513   gtk_object_set_data_full (GTK_OBJECT (window), 
514                             "gtk-embedded", embedded_windows,
515                             embedded_windows ?
516                               (GtkDestroyNotify) g_list_free : NULL);
517 }
518
519 static void
520 gtk_window_shutdown (GtkObject *object)
521 {
522   GtkWindow *window;
523
524   g_return_if_fail (object != NULL);
525   g_return_if_fail (GTK_IS_WINDOW (object));
526
527   window = GTK_WINDOW (object);
528
529   gtk_window_set_focus (window, NULL);
530   gtk_window_set_default (window, NULL);
531
532   GTK_OBJECT_CLASS (parent_class)->shutdown (object);
533 }
534
535 static void
536 gtk_window_destroy (GtkObject *object)
537 {
538   g_return_if_fail (object != NULL);
539   g_return_if_fail (GTK_IS_WINDOW (object));
540
541   gtk_container_unregister_toplevel (GTK_CONTAINER (object));
542
543   GTK_OBJECT_CLASS (parent_class)->destroy (object);
544 }
545
546 static void
547 gtk_window_finalize (GtkObject *object)
548 {
549   GtkWindow *window;
550
551   g_return_if_fail (object != NULL);
552   g_return_if_fail (GTK_IS_WINDOW (object));
553
554   window = GTK_WINDOW (object);
555   g_free (window->title);
556   g_free (window->wmclass_name);
557   g_free (window->wmclass_class);
558
559   GTK_OBJECT_CLASS(parent_class)->finalize (object);
560 }
561
562 static void
563 gtk_window_show (GtkWidget *widget)
564 {
565   g_return_if_fail (widget != NULL);
566   g_return_if_fail (GTK_IS_WINDOW (widget));
567
568   GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
569   gtk_container_check_resize (GTK_CONTAINER (widget));
570   gtk_widget_map (widget);
571
572   if (GTK_WINDOW(widget)->modal)
573       gtk_grab_add(widget);
574       
575 }
576
577 static void
578 gtk_window_hide (GtkWidget *widget)
579 {
580   g_return_if_fail (widget != NULL);
581   g_return_if_fail (GTK_IS_WINDOW (widget));
582
583   GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
584   gtk_widget_unmap (widget);
585
586   if (GTK_WINDOW(widget)->modal)
587       gtk_grab_remove(widget);
588
589 }
590
591 static void
592 gtk_window_map (GtkWidget *widget)
593 {
594   GtkWindow *window;
595
596   g_return_if_fail (widget != NULL);
597   g_return_if_fail (GTK_IS_WINDOW (widget));
598
599   GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
600
601   window = GTK_WINDOW (widget);
602
603   if (window->bin.child &&
604       GTK_WIDGET_VISIBLE (window->bin.child) &&
605       !GTK_WIDGET_MAPPED (window->bin.child))
606     gtk_widget_map (window->bin.child);
607
608   gtk_window_set_hints (widget, &widget->requisition);
609   gdk_window_show (widget->window);
610 }
611
612 static void
613 gtk_window_unmap (GtkWidget *widget)
614 {
615   GtkWindow *window;
616
617   g_return_if_fail (widget != NULL);
618   g_return_if_fail (GTK_IS_WINDOW (widget));
619
620   GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
621   gdk_window_hide (widget->window);
622
623   window = GTK_WINDOW (widget);
624   window->use_uposition = TRUE;
625 }
626
627 static void
628 gtk_window_realize (GtkWidget *widget)
629 {
630   GtkWindow *window;
631   GdkWindowAttr attributes;
632   gint attributes_mask;
633   
634   g_return_if_fail (widget != NULL);
635   g_return_if_fail (GTK_IS_WINDOW (widget));
636   
637   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
638   window = GTK_WINDOW (widget);
639   
640   switch (window->type)
641     {
642     case GTK_WINDOW_TOPLEVEL:
643       attributes.window_type = GDK_WINDOW_TOPLEVEL;
644       break;
645     case GTK_WINDOW_DIALOG:
646       attributes.window_type = GDK_WINDOW_DIALOG;
647       break;
648     case GTK_WINDOW_POPUP:
649       attributes.window_type = GDK_WINDOW_TEMP;
650       break;
651     }
652    
653   attributes.title = window->title;
654   attributes.wmclass_name = window->wmclass_name;
655   attributes.wmclass_class = window->wmclass_class;
656   attributes.width = widget->allocation.width;
657   attributes.height = widget->allocation.height;
658   attributes.wclass = GDK_INPUT_OUTPUT;
659   attributes.visual = gtk_widget_get_visual (widget);
660   attributes.colormap = gtk_widget_get_colormap (widget);
661   attributes.event_mask = gtk_widget_get_events (widget);
662   attributes.event_mask |= (GDK_EXPOSURE_MASK |
663                             GDK_KEY_PRESS_MASK |
664                             GDK_ENTER_NOTIFY_MASK |
665                             GDK_LEAVE_NOTIFY_MASK |
666                             GDK_FOCUS_CHANGE_MASK |
667                             GDK_STRUCTURE_MASK);
668    
669   attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
670   attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
671   attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
672    
673   widget->window = gdk_window_new (NULL, &attributes, attributes_mask);
674   gdk_window_set_user_data (widget->window, window);
675
676   widget->style = gtk_style_attach (widget->style, widget->window);
677   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
678   gtk_window_paint (widget, NULL);
679 }
680
681 static void
682 gtk_window_size_request (GtkWidget      *widget,
683                          GtkRequisition *requisition)
684 {
685   GtkWindow *window;
686
687   g_return_if_fail (widget != NULL);
688   g_return_if_fail (GTK_IS_WINDOW (widget));
689   g_return_if_fail (requisition != NULL);
690
691   window = GTK_WINDOW (widget);
692
693   if (window->bin.child)
694     {
695       requisition->width = GTK_CONTAINER (window)->border_width * 2;
696       requisition->height = GTK_CONTAINER (window)->border_width * 2;
697
698       gtk_widget_size_request (window->bin.child, &window->bin.child->requisition);
699
700       requisition->width += window->bin.child->requisition.width;
701       requisition->height += window->bin.child->requisition.height;
702     }
703   else
704     {
705       if (!GTK_WIDGET_VISIBLE (window))
706         GTK_CONTAINER (window)->need_resize = TRUE;
707     }
708 }
709
710 static void
711 gtk_window_size_allocate (GtkWidget     *widget,
712                           GtkAllocation *allocation)
713 {
714   GtkWindow *window;
715   GtkAllocation child_allocation;
716
717   g_return_if_fail (widget != NULL);
718   g_return_if_fail (GTK_IS_WINDOW (widget));
719   g_return_if_fail (allocation != NULL);
720
721   window = GTK_WINDOW (widget);
722   widget->allocation = *allocation;
723
724   if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
725     {
726       child_allocation.x = GTK_CONTAINER (window)->border_width;
727       child_allocation.y = GTK_CONTAINER (window)->border_width;
728       child_allocation.width = allocation->width - child_allocation.x * 2;
729       child_allocation.height = allocation->height - child_allocation.y * 2;
730
731       gtk_widget_size_allocate (window->bin.child, &child_allocation);
732     }
733 }
734
735 static gint
736 gtk_window_expose_event (GtkWidget      *widget,
737                          GdkEventExpose *event)
738 {
739   g_return_val_if_fail (widget != NULL, FALSE);
740   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
741   g_return_val_if_fail (event != NULL, FALSE);
742
743   if (GTK_WIDGET_DRAWABLE (widget))
744     if (GTK_WIDGET_CLASS (parent_class)->expose_event)
745       return (* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event);
746   
747   return FALSE;
748 }
749
750 static gint
751 gtk_window_configure_event (GtkWidget         *widget,
752                             GdkEventConfigure *event)
753 {
754   GtkWindow *window;
755   GtkAllocation allocation;
756   gboolean need_expose = FALSE;
757   
758   g_return_val_if_fail (widget != NULL, FALSE);
759   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
760   g_return_val_if_fail (event != NULL, FALSE);
761   
762   window = GTK_WINDOW (widget);
763
764   /* If the window was merely moved, do nothing */
765   if ((widget->allocation.width == event->width) &&
766       (widget->allocation.height == event->height))
767     {
768       if (window->resize_count == 0)      /* The window was merely moved */
769         return FALSE;
770       else
771         {
772           /* We asked for a new size, which was rejected, so the
773            * WM sent us a synthetic configure event. We won't
774            * get the expose event we would normally get (since
775            * we have ForgetGravity), so we need to fake it.
776            */
777           need_expose = TRUE;
778         }
779     }
780         
781   
782   window->handling_resize = TRUE;
783   
784   allocation.x = 0;
785   allocation.y = 0;
786   allocation.width = event->width;
787   allocation.height = event->height;
788   
789   gtk_widget_size_allocate (widget, &allocation);
790   
791   if (window->bin.child &&
792       GTK_WIDGET_VISIBLE (window->bin.child) &&
793       !GTK_WIDGET_MAPPED (window->bin.child))
794     gtk_widget_map (window->bin.child);
795   
796   if (window->resize_count > 0)
797       window->resize_count -= 1;
798   
799   if (need_expose)
800     {
801       GdkEvent temp_event;
802       temp_event.type = GDK_EXPOSE;
803       temp_event.expose.window = widget->window;
804       temp_event.expose.send_event = TRUE;
805       temp_event.expose.area.x = 0;
806       temp_event.expose.area.y = 0;
807       temp_event.expose.area.width = event->width;
808       temp_event.expose.area.height = event->height;
809       temp_event.expose.count = 0;
810       
811       gtk_widget_event (widget, &temp_event);
812     }
813
814   window->handling_resize = FALSE;
815   
816   return FALSE;
817 }
818
819 static gint
820 gtk_window_key_press_event (GtkWidget   *widget,
821                             GdkEventKey *event)
822 {
823   GtkWindow *window;
824   GtkDirectionType direction = 0;
825   gboolean handled;
826
827   g_return_val_if_fail (widget != NULL, FALSE);
828   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
829   g_return_val_if_fail (event != NULL, FALSE);
830
831   window = GTK_WINDOW (widget);
832
833   handled = FALSE;
834   
835   if (window->focus_widget)
836     {
837       handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
838     }
839     
840   if (!handled)
841     handled = gtk_accel_groups_activate (GTK_OBJECT (window), event->keyval, event->state);
842
843   if (!handled)
844     {
845       switch (event->keyval)
846         {
847         case GDK_space:
848           if (window->focus_widget)
849             {
850               gtk_widget_activate (window->focus_widget);
851               handled = TRUE;
852             }
853           break;
854         case GDK_Return:
855         case GDK_KP_Enter:
856           if (window->default_widget)
857             {
858               gtk_widget_activate (window->default_widget);
859               handled = TRUE;
860             }
861           else if (window->focus_widget)
862             {
863               gtk_widget_activate (window->focus_widget);
864               handled = TRUE;
865             }
866           break;
867         case GDK_Up:
868         case GDK_Down:
869         case GDK_Left:
870         case GDK_Right:
871         case GDK_Tab:
872         case GDK_ISO_Left_Tab:
873           switch (event->keyval)
874             {
875             case GDK_Up:
876               direction = GTK_DIR_UP;
877               break;
878             case GDK_Down:
879               direction = GTK_DIR_DOWN;
880               break;
881             case GDK_Left:
882               direction = GTK_DIR_LEFT;
883               break;
884             case GDK_Right:
885               direction = GTK_DIR_RIGHT;
886               break;
887             case GDK_Tab:
888             case GDK_ISO_Left_Tab:
889               if (event->state & GDK_SHIFT_MASK)
890                 direction = GTK_DIR_TAB_BACKWARD;
891               else
892                 direction = GTK_DIR_TAB_FORWARD;
893               break;
894             default :
895               direction = GTK_DIR_UP; /* never reached, but makes compiler happy */
896             }
897
898           gtk_container_focus (GTK_CONTAINER (widget), direction);
899
900           if (!GTK_CONTAINER (window)->focus_child)
901             gtk_window_set_focus (GTK_WINDOW (widget), NULL);
902           else
903             handled = TRUE;
904           break;
905         }
906     }
907
908   if (!handled && GTK_WIDGET_CLASS (parent_class)->key_press_event)
909     handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
910
911   return handled;
912 }
913
914 static gint
915 gtk_window_key_release_event (GtkWidget   *widget,
916                               GdkEventKey *event)
917 {
918   GtkWindow *window;
919   gint handled;
920   
921   g_return_val_if_fail (widget != NULL, FALSE);
922   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
923   g_return_val_if_fail (event != NULL, FALSE);
924   
925   window = GTK_WINDOW (widget);
926   handled = FALSE;
927   if (window->focus_widget)
928     {
929       handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
930     }
931
932   if (!handled && GTK_WIDGET_CLASS (parent_class)->key_release_event)
933     handled = GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
934
935   return handled;
936 }
937
938 static gint
939 gtk_window_enter_notify_event (GtkWidget        *widget,
940                                GdkEventCrossing *event)
941 {
942   g_return_val_if_fail (widget != NULL, FALSE);
943   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
944   g_return_val_if_fail (event != NULL, FALSE);
945
946   return FALSE;
947 }
948
949 static gint
950 gtk_window_leave_notify_event (GtkWidget        *widget,
951                                GdkEventCrossing *event)
952 {
953   g_return_val_if_fail (widget != NULL, FALSE);
954   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
955   g_return_val_if_fail (event != NULL, FALSE);
956
957   return FALSE;
958 }
959
960 static gint
961 gtk_window_focus_in_event (GtkWidget     *widget,
962                            GdkEventFocus *event)
963 {
964   GtkWindow *window;
965   GdkEventFocus fevent;
966
967   g_return_val_if_fail (widget != NULL, FALSE);
968   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
969   g_return_val_if_fail (event != NULL, FALSE);
970
971   /* It appears spurious focus in events can occur when
972    *  the window is hidden. So we'll just check to see if
973    *  the window is visible before actually handling the
974    *  event
975    */
976   if (GTK_WIDGET_VISIBLE (widget))
977     {
978       window = GTK_WINDOW (widget);
979       if (window->focus_widget && !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
980         {
981           fevent.type = GDK_FOCUS_CHANGE;
982           fevent.window = window->focus_widget->window;
983           fevent.in = TRUE;
984
985           gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
986         }
987     }
988
989   return FALSE;
990 }
991
992 static gint
993 gtk_window_focus_out_event (GtkWidget     *widget,
994                             GdkEventFocus *event)
995 {
996   GtkWindow *window;
997   GdkEventFocus fevent;
998
999   g_return_val_if_fail (widget != NULL, FALSE);
1000   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1001   g_return_val_if_fail (event != NULL, FALSE);
1002
1003   window = GTK_WINDOW (widget);
1004   if (window->focus_widget && GTK_WIDGET_HAS_FOCUS (window->focus_widget))
1005     {
1006       fevent.type = GDK_FOCUS_CHANGE;
1007       fevent.window = window->focus_widget->window;
1008       fevent.in = FALSE;
1009
1010       gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
1011     }
1012
1013   return FALSE;
1014 }
1015
1016 static GdkAtom atom_rcfiles = GDK_NONE;
1017
1018 static void
1019 gtk_window_read_rcfiles (GtkWidget *widget,
1020                          GdkEventClient *event)
1021 {
1022   GList *embedded_windows;
1023
1024   embedded_windows = gtk_object_get_data (GTK_OBJECT (widget), "gtk-embedded");
1025   if (embedded_windows)
1026     {
1027       GdkEventClient sev;
1028       int i;
1029       
1030       for(i = 0; i < 5; i++)
1031         sev.data.l[i] = 0;
1032       sev.data_format = 32;
1033       sev.message_type = atom_rcfiles;
1034       
1035       while (embedded_windows)
1036         {
1037           guint xid = GPOINTER_TO_UINT (embedded_windows->data);
1038           gdk_event_send_client_message ((GdkEvent *) &sev, xid);
1039           embedded_windows = embedded_windows->next;
1040         }
1041     }
1042
1043   if (gtk_rc_reparse_all ())
1044     {
1045       /* If the above returned true, some of our RC files are out
1046        * of date, so we need to reset all our widgets. Our other
1047        * toplevel windows will also get the message, but by
1048        * then, the RC file will up to date, so we have to tell
1049        * them now.
1050        */
1051       GList *toplevels;
1052       
1053       toplevels = gtk_container_get_toplevels();
1054       while (toplevels)
1055         {
1056           gtk_widget_reset_rc_styles (toplevels->data);
1057           toplevels = toplevels->next;
1058         }
1059     }
1060 }
1061
1062 static gint
1063 gtk_window_client_event (GtkWidget      *widget,
1064                          GdkEventClient *event)
1065 {
1066   g_return_val_if_fail (widget != NULL, FALSE);
1067   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1068   g_return_val_if_fail (event != NULL, FALSE);
1069
1070   if (!atom_rcfiles)
1071     atom_rcfiles = gdk_atom_intern("_GTK_READ_RCFILES", FALSE);
1072
1073   if(event->message_type == atom_rcfiles) 
1074     gtk_window_read_rcfiles (widget, event);    
1075
1076   return FALSE;
1077 }
1078
1079 static void
1080 gtk_window_check_resize (GtkContainer *container)
1081 {
1082   GtkWindow *window;
1083
1084   g_return_if_fail (container != NULL);
1085   g_return_if_fail (GTK_IS_WINDOW (container));
1086
1087   window = GTK_WINDOW (container);
1088   if (!window->handling_resize)
1089     {
1090       if (GTK_WIDGET_VISIBLE (container))
1091         gtk_window_move_resize (window);
1092       else
1093         GTK_CONTAINER (window)->need_resize = TRUE;
1094     }
1095 }
1096
1097 /* FIXME: we leave container->resize_widgets set under some
1098    circumstances ? */
1099 static void
1100 gtk_window_move_resize (GtkWindow *window)
1101 {
1102   GtkWidget    *widget;
1103   GtkContainer *container;
1104   gint x, y;
1105   gint width, height;
1106   gint screen_width;
1107   gint screen_height;
1108   gboolean needed_resize;
1109   gboolean size_changed;
1110
1111   g_return_if_fail (window != NULL);
1112   g_return_if_fail (GTK_IS_WINDOW (window));
1113
1114   widget = GTK_WIDGET (window);
1115   container = GTK_CONTAINER (widget);
1116
1117   /* Remember old size, to know if we have to reset hints */
1118   width = widget->requisition.width;
1119   height = widget->requisition.height;
1120   gtk_widget_size_request (widget, &widget->requisition);
1121
1122   size_changed = ((width != widget->requisition.width) ||
1123                   (height != widget->requisition.height));
1124   
1125   if (size_changed)
1126     {
1127       gboolean saved_use_upos;
1128
1129       saved_use_upos = window->use_uposition;
1130       gtk_window_set_hints (widget, &widget->requisition);
1131       window->use_uposition = saved_use_upos;
1132     }
1133   
1134   x = -1;
1135   y = -1;
1136   width = widget->requisition.width;
1137   height = widget->requisition.height;
1138   
1139   if (window->use_uposition)
1140     switch (window->position)
1141       {
1142       case GTK_WIN_POS_CENTER:
1143         x = (gdk_screen_width () - width) / 2;
1144         y = (gdk_screen_height () - height) / 2;
1145         gtk_widget_set_uposition (widget, x, y);
1146         break;
1147       case GTK_WIN_POS_MOUSE:
1148         gdk_window_get_pointer (NULL, &x, &y, NULL);
1149         
1150         x -= width / 2;
1151         y -= height / 2;
1152         
1153         screen_width = gdk_screen_width ();
1154         screen_height = gdk_screen_height ();
1155         
1156         if (x < 0)
1157           x = 0;
1158         else if (x > (screen_width - width))
1159           x = screen_width - width;
1160         
1161         if (y < 0)
1162           y = 0;
1163         else if (y > (screen_height - height))
1164           y = screen_height - height;
1165         
1166         gtk_widget_set_uposition (widget, x, y);
1167         break;
1168       }
1169
1170   /* Now, do the resizing */
1171
1172   needed_resize = container->need_resize;
1173   container->need_resize = FALSE;
1174
1175   if ((widget->requisition.width == 0) ||
1176       (widget->requisition.height == 0))
1177     {
1178       widget->requisition.width = 200;
1179       widget->requisition.height = 200;
1180     }
1181   
1182   if (!GTK_WIDGET_REALIZED (window))
1183     {
1184       GtkAllocation allocation;
1185
1186       allocation.x = 0;
1187       allocation.y = 0;
1188       allocation.width = widget->requisition.width;
1189       allocation.height = widget->requisition.height;
1190       
1191       gtk_widget_size_allocate (widget, &allocation);
1192
1193       return;
1194     }
1195   
1196   gdk_window_get_geometry (widget->window, NULL, NULL, &width, &height, NULL);
1197   
1198   /* As an optimization, we don't try to get a new size from the
1199    * window manager if we asked for the same size last time and
1200    * didn't get it */
1201
1202   if (size_changed && 
1203       (((window->auto_shrink &&
1204         ((width != widget->requisition.width) ||
1205          (height != widget->requisition.height)))) ||
1206        ((width < widget->requisition.width) ||
1207         (height < widget->requisition.height))))
1208     {
1209       window->resize_count += 1;
1210       if ((x != -1) && (y != -1))
1211         gdk_window_move_resize (widget->window, x, y,
1212                                 widget->requisition.width,
1213                                 widget->requisition.height);
1214       else
1215         gdk_window_resize (widget->window,
1216                            widget->requisition.width,
1217                            widget->requisition.height);
1218     }
1219   else if (needed_resize)
1220     {
1221       /* The windows contents changed size while it was not
1222        * visible, so reallocate everything, since we didn't
1223        * keep track of what changed
1224        */
1225       GtkAllocation allocation;
1226       
1227       allocation.x = 0;
1228       allocation.y = 0;
1229       allocation.width = widget->requisition.width;
1230       allocation.height = widget->requisition.height;
1231       
1232       gtk_widget_size_allocate (widget, &allocation);
1233     }
1234   else
1235     {
1236       if ((x != -1) && (y != -1))
1237         gdk_window_move (widget->window, x, y);
1238       
1239       gtk_container_resize_children (GTK_CONTAINER (window));
1240     }
1241 }
1242
1243 static void
1244 gtk_real_window_set_focus (GtkWindow *window,
1245                            GtkWidget *focus)
1246 {
1247   GdkEventFocus event;
1248
1249   g_return_if_fail (window != NULL);
1250   g_return_if_fail (GTK_IS_WINDOW (window));
1251
1252   if (focus && !GTK_WIDGET_CAN_FOCUS (focus))
1253     return;
1254
1255   if (window->focus_widget != focus)
1256     {
1257       if (window->focus_widget)
1258         {
1259           event.type = GDK_FOCUS_CHANGE;
1260           event.window = window->focus_widget->window;
1261           event.in = FALSE;
1262
1263           gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
1264         }
1265
1266       window->focus_widget = focus;
1267
1268       if (window->focus_widget)
1269         {
1270           event.type = GDK_FOCUS_CHANGE;
1271           event.window = window->focus_widget->window;
1272           event.in = TRUE;
1273
1274           gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
1275         }
1276     }
1277 }
1278
1279 static void
1280 gtk_window_set_hints (GtkWidget      *widget,
1281                       GtkRequisition *requisition)
1282 {
1283   GtkWindow *window;
1284   GtkWidgetAuxInfo *aux_info;
1285   gint flags;
1286   gint ux, uy;
1287
1288   g_return_if_fail (widget != NULL);
1289   g_return_if_fail (GTK_IS_WINDOW (widget));
1290   g_return_if_fail (requisition != NULL);
1291
1292   if (GTK_WIDGET_REALIZED (widget))
1293     {
1294       window = GTK_WINDOW (widget);
1295
1296       flags = 0;
1297       ux = 0;
1298       uy = 0;
1299
1300       aux_info = gtk_object_get_data (GTK_OBJECT (widget), "gtk-aux-info");
1301       if (aux_info && (aux_info->x != -1) && (aux_info->y != -1))
1302         {
1303           ux = aux_info->x;
1304           uy = aux_info->y;
1305           flags |= GDK_HINT_POS;
1306         }
1307
1308       if (!window->allow_shrink)
1309         flags |= GDK_HINT_MIN_SIZE;
1310       if (!window->allow_grow)
1311         flags |= GDK_HINT_MAX_SIZE;
1312
1313       gdk_window_set_hints (widget->window, ux, uy,
1314                             requisition->width, requisition->height,
1315                             requisition->width, requisition->height,
1316                             flags);
1317
1318       if (window->use_uposition && (flags & GDK_HINT_POS))
1319         {
1320           window->use_uposition = FALSE;
1321           gdk_window_move (widget->window, ux, uy);
1322         }
1323     }
1324 }
1325
1326 static void
1327 gtk_window_paint (GtkWidget     *widget,
1328                   GdkRectangle *area)
1329 {
1330   gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL, 
1331                       GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
1332 }
1333
1334 static gint
1335 gtk_window_expose (GtkWidget      *widget,
1336                    GdkEventExpose *event)
1337 {
1338   g_return_val_if_fail (widget != NULL, FALSE);
1339   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1340   g_return_val_if_fail (event != NULL, FALSE);
1341
1342   gtk_window_paint (widget, &event->area);
1343   
1344   if (GTK_WIDGET_CLASS (parent_class)->expose_event)
1345     return (* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event);
1346
1347   return FALSE;
1348 }
1349
1350 static void
1351 gtk_window_draw (GtkWidget    *widget,
1352                  GdkRectangle *area)
1353 {
1354   gtk_window_paint (widget, area);
1355   
1356   if (GTK_WIDGET_CLASS (parent_class)->draw)
1357     (* GTK_WIDGET_CLASS (parent_class)->draw) (widget, area);
1358 }
1359
1360 static void
1361 gtk_window_style_set (GtkWidget *widget,
1362                       GtkStyle  *previous_style)
1363 {
1364    GdkRectangle area;
1365    
1366    if (GTK_WIDGET_REALIZED (widget) &&
1367        !GTK_WIDGET_NO_WINDOW (widget))
1368      {
1369         gtk_style_set_background (widget->style, widget->window, widget->state);
1370
1371         area.x = 0;
1372         area.y = 0;
1373         area.width = widget->allocation.width;
1374         area.height = widget->allocation.height;
1375         gtk_window_draw(widget, &area);
1376
1377         if (GTK_WIDGET_DRAWABLE (widget))
1378           gdk_window_clear (widget->window);
1379      }
1380 }