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