]> Pileus Git - ~andy/gtk/blob - gtk/gtkwindow.c
Remove draw_focus and draw_default (gtk_widget_draw_focus): remove this
[~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 Lesser 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  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser 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
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #include <string.h>
28 #include <limits.h>
29 #include "gdk/gdk.h"
30 #include "gdk/gdkkeysyms.h"
31
32 #if defined (GDK_WINDOWING_X11)
33 #include "x11/gdkx.h"
34 #elif defined (GDK_WINDOWING_WIN32)
35 #include "win32/gdkwin32.h"
36 #elif defined (GDK_WINDOWING_NANOX)
37 #include "nanox/gdkprivate-nanox.h"
38 #elif defined (GDK_WINDOWING_FB)
39 #include "linux-fb/gdkfb.h"
40 #endif
41
42 #include "gtkprivate.h"
43 #include "gtkrc.h"
44 #include "gtksignal.h"
45 #include "gtkwindow.h"
46 #include "gtkwindow-decorate.h"
47 #include "gtkbindings.h"
48 #include "gtkmain.h"
49 #include "gtkiconfactory.h"
50
51 /* TODO: remove this define and assorted code in 1.3 and fix up the
52  * real culprits.
53  */
54 #define FIXME_ZVT_ME_HARDER
55
56 enum {
57   SET_FOCUS,
58   FRAME_EVENT,
59   LAST_SIGNAL
60 };
61
62 enum {
63   ARG_0,
64   ARG_TYPE,
65   ARG_TITLE,
66   ARG_AUTO_SHRINK,
67   ARG_ALLOW_SHRINK,
68   ARG_ALLOW_GROW,
69   ARG_MODAL,
70   ARG_WIN_POS,
71   ARG_DEFAULT_WIDTH,
72   ARG_DEFAULT_HEIGHT,
73   ARG_DESTROY_WITH_PARENT
74 };
75
76 typedef struct {
77   GdkGeometry    geometry; /* Last set of geometry hints we set */
78   GdkWindowHints flags;
79   gint           width;
80   gint           height;
81 } GtkWindowLastGeometryInfo;
82
83 typedef struct {
84   /* Properties that the app has set on the window
85    */
86   GdkGeometry    geometry;      /* Geometry hints */
87   GdkWindowHints mask;
88   GtkWidget     *widget;        /* subwidget to which hints apply */
89   gint           width;         /* Default size */
90   gint           height;
91
92   GtkWindowLastGeometryInfo last;
93 } GtkWindowGeometryInfo;
94
95 static void gtk_window_class_init         (GtkWindowClass    *klass);
96 static void gtk_window_init               (GtkWindow         *window);
97 static void gtk_window_set_arg            (GtkObject         *object,
98                                            GtkArg            *arg,
99                                            guint              arg_id);
100 static void gtk_window_get_arg            (GtkObject         *object,
101                                            GtkArg            *arg,
102                                            guint              arg_id);
103 static void gtk_window_shutdown           (GObject           *object);
104 static void gtk_window_destroy            (GtkObject         *object);
105 static void gtk_window_finalize           (GObject           *object);
106 static void gtk_window_show               (GtkWidget         *widget);
107 static void gtk_window_hide               (GtkWidget         *widget);
108 static void gtk_window_map                (GtkWidget         *widget);
109 static void gtk_window_unmap              (GtkWidget         *widget);
110 static void gtk_window_realize            (GtkWidget         *widget);
111 static void gtk_window_unrealize          (GtkWidget         *widget);
112 static void gtk_window_size_request       (GtkWidget         *widget,
113                                            GtkRequisition    *requisition);
114 static void gtk_window_size_allocate      (GtkWidget         *widget,
115                                            GtkAllocation     *allocation);
116 static gint gtk_window_event              (GtkWidget *widget,
117                                            GdkEvent *event);
118 static gboolean gtk_window_frame_event    (GtkWidget *widget,
119                                            GdkEvent *event);
120 static gint gtk_window_configure_event    (GtkWidget         *widget,
121                                            GdkEventConfigure *event);
122 static gint gtk_window_key_press_event    (GtkWidget         *widget,
123                                            GdkEventKey       *event);
124 static gint gtk_window_key_release_event  (GtkWidget         *widget,
125                                            GdkEventKey       *event);
126 static gint gtk_window_enter_notify_event (GtkWidget         *widget,
127                                            GdkEventCrossing  *event);
128 static gint gtk_window_leave_notify_event (GtkWidget         *widget,
129                                            GdkEventCrossing  *event);
130 static gint gtk_window_focus_in_event     (GtkWidget         *widget,
131                                            GdkEventFocus     *event);
132 static gint gtk_window_focus_out_event    (GtkWidget         *widget,
133                                            GdkEventFocus     *event);
134 static gint gtk_window_client_event       (GtkWidget         *widget,
135                                            GdkEventClient    *event);
136 static void gtk_window_check_resize       (GtkContainer      *container);
137 static gint gtk_window_focus              (GtkContainer     *container,
138                                            GtkDirectionType  direction);
139 static void gtk_window_real_set_focus     (GtkWindow         *window,
140                                            GtkWidget         *focus);
141
142 static void gtk_window_move_resize        (GtkWindow         *window);
143 static gboolean gtk_window_compare_hints  (GdkGeometry       *geometry_a,
144                                            guint              flags_a,
145                                            GdkGeometry       *geometry_b,
146                                            guint              flags_b);
147 static void gtk_window_compute_default_size (GtkWindow       *window,
148                                              guint           *width,
149                                              guint           *height);
150 static void  gtk_window_constrain_size      (GtkWindow       *window,
151                                              GdkGeometry     *geometry,
152                                              guint            flags,
153                                              gint             width,
154                                              gint             height,
155                                              gint            *new_width,
156                                              gint            *new_height);
157 static void gtk_window_compute_hints      (GtkWindow         *window, 
158                                            GdkGeometry       *new_geometry,
159                                            guint             *new_flags);
160 static void gtk_window_compute_reposition (GtkWindow         *window,
161                                            gint               new_width,
162                                            gint               new_height,
163                                            gint              *x,
164                                            gint              *y);
165
166 static void gtk_window_read_rcfiles       (GtkWidget         *widget,
167                                            GdkEventClient    *event);
168 static void gtk_window_paint              (GtkWidget         *widget,
169                                            GdkRectangle      *area);
170 static gint gtk_window_expose             (GtkWidget         *widget,
171                                            GdkEventExpose    *event);
172 static void gtk_window_unset_transient_for         (GtkWindow  *window);
173 static void gtk_window_transient_parent_realized   (GtkWidget  *parent,
174                                                     GtkWidget  *window);
175 static void gtk_window_transient_parent_unrealized (GtkWidget  *parent,
176                                                     GtkWidget  *window);
177
178 static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
179                                                             gboolean   create);
180 static void gtk_window_geometry_destroy  (GtkWindowGeometryInfo *info);
181
182
183 static GSList      *toplevel_list = NULL;
184 static GtkBinClass *parent_class = NULL;
185 static guint        window_signals[LAST_SIGNAL] = { 0 };
186
187
188 GtkType
189 gtk_window_get_type (void)
190 {
191   static GtkType window_type = 0;
192
193   if (!window_type)
194     {
195       static const GtkTypeInfo window_info =
196       {
197         "GtkWindow",
198         sizeof (GtkWindow),
199         sizeof (GtkWindowClass),
200         (GtkClassInitFunc) gtk_window_class_init,
201         (GtkObjectInitFunc) gtk_window_init,
202         /* reserved_1 */ NULL,
203         /* reserved_2 */ NULL,
204         (GtkClassInitFunc) NULL,
205       };
206
207       window_type = gtk_type_unique (gtk_bin_get_type (), &window_info);
208     }
209
210   return window_type;
211 }
212
213 static void
214 gtk_window_class_init (GtkWindowClass *klass)
215 {
216   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
217   GtkObjectClass *object_class;
218   GtkWidgetClass *widget_class;
219   GtkContainerClass *container_class;
220
221   object_class = (GtkObjectClass*) klass;
222   widget_class = (GtkWidgetClass*) klass;
223   container_class = (GtkContainerClass*) klass;
224
225   parent_class = gtk_type_class (gtk_bin_get_type ());
226
227   gobject_class->shutdown = gtk_window_shutdown;
228   gobject_class->finalize = gtk_window_finalize;
229
230   object_class->set_arg = gtk_window_set_arg;
231   object_class->get_arg = gtk_window_get_arg;
232   object_class->destroy = gtk_window_destroy;
233
234   widget_class->show = gtk_window_show;
235   widget_class->hide = gtk_window_hide;
236   widget_class->map = gtk_window_map;
237   widget_class->unmap = gtk_window_unmap;
238   widget_class->realize = gtk_window_realize;
239   widget_class->unrealize = gtk_window_unrealize;
240   widget_class->size_request = gtk_window_size_request;
241   widget_class->size_allocate = gtk_window_size_allocate;
242   widget_class->configure_event = gtk_window_configure_event;
243   widget_class->key_press_event = gtk_window_key_press_event;
244   widget_class->key_release_event = gtk_window_key_release_event;
245   widget_class->enter_notify_event = gtk_window_enter_notify_event;
246   widget_class->leave_notify_event = gtk_window_leave_notify_event;
247   widget_class->focus_in_event = gtk_window_focus_in_event;
248   widget_class->focus_out_event = gtk_window_focus_out_event;
249   widget_class->client_event = gtk_window_client_event;
250   
251   widget_class->expose_event = gtk_window_expose;
252    
253   container_class->check_resize = gtk_window_check_resize;
254   container_class->focus = gtk_window_focus;
255
256   klass->set_focus = gtk_window_real_set_focus;
257   klass->frame_event = gtk_window_frame_event;
258
259   gtk_object_add_arg_type ("GtkWindow::type", GTK_TYPE_WINDOW_TYPE, GTK_ARG_READWRITE, ARG_TYPE);
260   gtk_object_add_arg_type ("GtkWindow::title", GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_TITLE);
261   gtk_object_add_arg_type ("GtkWindow::auto_shrink", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_AUTO_SHRINK);
262   gtk_object_add_arg_type ("GtkWindow::allow_shrink", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_ALLOW_SHRINK);
263   gtk_object_add_arg_type ("GtkWindow::allow_grow", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_ALLOW_GROW);
264   gtk_object_add_arg_type ("GtkWindow::modal", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_MODAL);
265   gtk_object_add_arg_type ("GtkWindow::window_position", GTK_TYPE_WINDOW_POSITION, GTK_ARG_READWRITE, ARG_WIN_POS);
266   gtk_object_add_arg_type ("GtkWindow::default_width", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_DEFAULT_WIDTH);
267   gtk_object_add_arg_type ("GtkWindow::default_height", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_DEFAULT_HEIGHT);
268   gtk_object_add_arg_type ("GtkWindow::destroy_with_parent", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_DESTROY_WITH_PARENT);
269   
270   window_signals[SET_FOCUS] =
271     gtk_signal_new ("set_focus",
272                     GTK_RUN_LAST,
273                     GTK_CLASS_TYPE (object_class),
274                     GTK_SIGNAL_OFFSET (GtkWindowClass, set_focus),
275                     gtk_marshal_VOID__POINTER,
276                     GTK_TYPE_NONE, 1,
277                     GTK_TYPE_WIDGET);
278   
279   window_signals[FRAME_EVENT] =
280     gtk_signal_new ("frame_event",
281                     GTK_RUN_LAST,
282                     GTK_CLASS_TYPE (object_class),
283                     GTK_SIGNAL_OFFSET (GtkWindowClass, frame_event),
284                     gtk_marshal_BOOLEAN__POINTER,
285                     GTK_TYPE_BOOL, 1,
286                     GTK_TYPE_GDK_EVENT);
287 }
288
289 static void
290 gtk_window_init (GtkWindow *window)
291 {
292   GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
293   GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
294
295   gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
296
297   window->title = NULL;
298   window->wmclass_name = g_strdup (g_get_prgname ());
299   window->wmclass_class = g_strdup (gdk_progclass);
300   window->type = GTK_WINDOW_TOPLEVEL;
301   window->focus_widget = NULL;
302   window->default_widget = NULL;
303   window->resize_count = 0;
304   window->allow_shrink = FALSE;
305   window->allow_grow = TRUE;
306   window->auto_shrink = FALSE;
307   window->handling_resize = FALSE;
308   window->position = GTK_WIN_POS_NONE;
309   window->use_uposition = TRUE;
310   window->modal = FALSE;
311   window->frame = NULL;
312   window->has_frame = FALSE;
313   window->frame_left = 0;
314   window->frame_right = 0;
315   window->frame_top = 0;
316   window->frame_bottom = 0;
317     
318   gtk_widget_ref (GTK_WIDGET (window));
319   gtk_object_sink (GTK_OBJECT (window));
320   window->has_user_ref_count = TRUE;
321   toplevel_list = g_slist_prepend (toplevel_list, window);
322
323   gtk_decorated_window_init (window);
324
325   gtk_signal_connect (GTK_OBJECT (window),
326                       "event",
327                       GTK_SIGNAL_FUNC (gtk_window_event),
328                       NULL);
329 }
330
331 static void
332 gtk_window_set_arg (GtkObject  *object,
333                     GtkArg     *arg,
334                     guint       arg_id)
335 {
336   GtkWindow  *window;
337
338   window = GTK_WINDOW (object);
339
340   switch (arg_id)
341     {
342     case ARG_TYPE:
343       window->type = GTK_VALUE_ENUM (*arg);
344       break;
345     case ARG_TITLE:
346       gtk_window_set_title (window, GTK_VALUE_STRING (*arg));
347       break;
348     case ARG_AUTO_SHRINK:
349       window->auto_shrink = (GTK_VALUE_BOOL (*arg) != FALSE);
350       gtk_widget_queue_resize (GTK_WIDGET (window));
351       break;
352     case ARG_ALLOW_SHRINK:
353       window->allow_shrink = (GTK_VALUE_BOOL (*arg) != FALSE);
354       gtk_widget_queue_resize (GTK_WIDGET (window));
355       break;
356     case ARG_ALLOW_GROW:
357       window->allow_grow = (GTK_VALUE_BOOL (*arg) != FALSE);
358       gtk_widget_queue_resize (GTK_WIDGET (window));
359       break;
360     case ARG_MODAL:
361       gtk_window_set_modal (window, GTK_VALUE_BOOL (*arg));
362       break;
363     case ARG_WIN_POS:
364       gtk_window_set_position (window, GTK_VALUE_ENUM (*arg));
365       break;
366     case ARG_DEFAULT_WIDTH:
367       gtk_window_set_default_size (window, GTK_VALUE_INT (*arg), -2);
368       break;
369     case ARG_DEFAULT_HEIGHT:
370       gtk_window_set_default_size (window, -2, GTK_VALUE_INT (*arg));
371       break;
372     case ARG_DESTROY_WITH_PARENT:
373       gtk_window_set_destroy_with_parent (window, GTK_VALUE_BOOL (*arg));
374       break;
375     default:
376       break;
377     }
378 }
379
380 static void
381 gtk_window_get_arg (GtkObject  *object,
382                     GtkArg     *arg,
383                     guint       arg_id)
384 {
385   GtkWindow  *window;
386
387   window = GTK_WINDOW (object);
388
389   switch (arg_id)
390     {
391       GtkWindowGeometryInfo *info;
392     case ARG_TYPE:
393       GTK_VALUE_ENUM (*arg) = window->type;
394       break;
395     case ARG_TITLE:
396       GTK_VALUE_STRING (*arg) = g_strdup (window->title);
397       break;
398     case ARG_AUTO_SHRINK:
399       GTK_VALUE_BOOL (*arg) = window->auto_shrink;
400       break;
401     case ARG_ALLOW_SHRINK:
402       GTK_VALUE_BOOL (*arg) = window->allow_shrink;
403       break;
404     case ARG_ALLOW_GROW:
405       GTK_VALUE_BOOL (*arg) = window->allow_grow;
406       break;
407     case ARG_MODAL:
408       GTK_VALUE_BOOL (*arg) = window->modal;
409       break;
410     case ARG_WIN_POS:
411       GTK_VALUE_ENUM (*arg) = window->position;
412       break;
413     case ARG_DEFAULT_WIDTH:
414       info = gtk_window_get_geometry_info (window, FALSE);
415       if (!info)
416         GTK_VALUE_INT (*arg) = -1;
417       else
418         GTK_VALUE_INT (*arg) = info->width;
419       break;
420     case ARG_DEFAULT_HEIGHT:
421       info = gtk_window_get_geometry_info (window, FALSE);
422       if (!info)
423         GTK_VALUE_INT (*arg) = -1;
424       else
425         GTK_VALUE_INT (*arg) = info->height;
426       break;
427     case ARG_DESTROY_WITH_PARENT:
428       GTK_VALUE_BOOL (*arg) = window->destroy_with_parent;
429       break;
430     default:
431       arg->type = GTK_TYPE_INVALID;
432       break;
433     }
434 }
435
436 /**
437  * gtk_window_new:
438  * @type: type of window
439  * 
440  * Creates a new #GtkWindow, which is a toplevel window that can
441  * contain other widgets. Nearly always, the type of the window should
442  * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
443  * popup menu from scratch (which is a bad idea, just use #GtkMenu),
444  * you might use #GTK_WINDOW_TOPLEVEL. #GTK_WINDOW_DIALOG is not
445  * useful; dialogs should be of type #GTK_WINDOW_TOPLEVEL.  (Probably
446  * you want to use the #GtkDialog widget for dialogs anyway).
447  * 
448  * Return value: a new #GtkWindow.
449  **/
450 GtkWidget*
451 gtk_window_new (GtkWindowType type)
452 {
453   GtkWindow *window;
454
455   g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
456
457   window = gtk_type_new (GTK_TYPE_WINDOW);
458
459   window->type = type;
460
461   return GTK_WIDGET (window);
462 }
463
464 /**
465  * gtk_window_set_title:
466  * @window: a #GtkWindow
467  * @title: title of the window
468  * 
469  * Sets the title of the #GtkWindow. The title of a window will be displayed in
470  * its title bar; on the X Window System, the title bar is rendered by the
471  * window manager, so exactly how the title appears to users may vary according
472  * to a user's exact configuration. The title should help a user distinguish
473  * this window from other windows they may have open. A good title might
474  * include the application name and current document filename, for example.
475  * 
476  **/
477 void
478 gtk_window_set_title (GtkWindow   *window,
479                       const gchar *title)
480 {
481   g_return_if_fail (window != NULL);
482   g_return_if_fail (GTK_IS_WINDOW (window));
483
484   if (window->title)
485     g_free (window->title);
486   window->title = g_strdup (title);
487
488   if (GTK_WIDGET_REALIZED (window))
489     {
490       gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
491
492       gtk_decorated_window_set_title (window, title);
493     }
494 }
495
496 /**
497  * gtk_window_set_wmclass:
498  * @window: a #GtkWindow
499  * @wmclass_name: window name hint
500  * @wmclass_class: window class hint
501  *
502  * This function sets the X Window System "class" and "name" hints for a window.
503  * According to the ICCCM, you should always set these to the same value for
504  * all windows in an application, and GTK sets them to that value by default,
505  * so calling this function is sort of pointless. However, you may want to
506  * call gtk_window_set_role() on each window in your application, for the
507  * benefit of the session manager. Setting the role allows the window manager
508  * to restore window positions when loading a saved session.
509  * 
510  **/
511 void
512 gtk_window_set_wmclass (GtkWindow *window,
513                         const gchar *wmclass_name,
514                         const gchar *wmclass_class)
515 {
516   g_return_if_fail (window != NULL);
517   g_return_if_fail (GTK_IS_WINDOW (window));
518
519   g_free (window->wmclass_name);
520   window->wmclass_name = g_strdup (wmclass_name);
521
522   g_free (window->wmclass_class);
523   window->wmclass_class = g_strdup (wmclass_class);
524
525   if (GTK_WIDGET_REALIZED (window))
526     g_warning ("shouldn't set wmclass after window is realized!\n");
527 }
528
529 /**
530  * gtk_window_set_focus:
531  * @window: a #GtkWindow
532  * @focus: widget to be the new focus widget
533  *
534  * If @focus is not the current focus widget, and is focusable, emits
535  * the "set_focus" signal to set @focus as the focus widget for the
536  * window.  This function is more or less GTK-internal; to focus an
537  * entry widget or the like, you should use gtk_widget_grab_focus()
538  * instead of this function.
539  * 
540  **/
541 void
542 gtk_window_set_focus (GtkWindow *window,
543                       GtkWidget *focus)
544 {
545   g_return_if_fail (window != NULL);
546   g_return_if_fail (GTK_IS_WINDOW (window));
547   if (focus)
548     {
549       g_return_if_fail (GTK_IS_WIDGET (focus));
550       g_return_if_fail (GTK_WIDGET_CAN_FOCUS (focus));
551     }
552
553   if ((window->focus_widget != focus) ||
554       (focus && !GTK_WIDGET_HAS_FOCUS (focus)))
555     gtk_signal_emit (GTK_OBJECT (window), window_signals[SET_FOCUS], focus);
556 }
557
558 /**
559  * gtk_window_set_default:
560  * @window: a #GtkWindow
561  * @default_widget: widget to be the default
562  *
563  * The default widget is the widget that's activated when the user
564  * presses Enter in a dialog (for example). This function tells a
565  * #GtkWindow about the current default widget; it's really a GTK
566  * internal function and you shouldn't need it. Instead, to change the
567  * default widget, first set the #GTK_CAN_DEFAULT flag on the widget
568  * you'd like to make the default using GTK_WIDGET_SET_FLAGS(), then
569  * call gtk_widget_grab_default() to move the default.
570  * 
571  **/
572 void
573 gtk_window_set_default (GtkWindow *window,
574                         GtkWidget *default_widget)
575 {
576   g_return_if_fail (window != NULL);
577   g_return_if_fail (GTK_IS_WINDOW (window));
578
579   if (default_widget)
580     g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
581
582   if (window->default_widget != default_widget)
583     {
584       if (window->default_widget)
585         {
586           if (window->focus_widget != window->default_widget ||
587               !GTK_WIDGET_RECEIVES_DEFAULT (window->default_widget))
588             GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
589           gtk_widget_queue_draw (window->default_widget);
590         }
591
592       window->default_widget = default_widget;
593
594       if (window->default_widget)
595         {
596           if (window->focus_widget == NULL ||
597               !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))
598             GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
599           gtk_widget_queue_draw (window->default_widget);
600         }
601     }
602 }
603
604 void
605 gtk_window_set_policy (GtkWindow *window,
606                        gint       allow_shrink,
607                        gint       allow_grow,
608                        gint       auto_shrink)
609 {
610   g_return_if_fail (window != NULL);
611   g_return_if_fail (GTK_IS_WINDOW (window));
612
613   window->allow_shrink = (allow_shrink != FALSE);
614   window->allow_grow = (allow_grow != FALSE);
615   window->auto_shrink = (auto_shrink != FALSE);
616
617   gtk_widget_queue_resize (GTK_WIDGET (window));
618 }
619
620 void
621 gtk_window_add_accel_group (GtkWindow        *window,
622                             GtkAccelGroup    *accel_group)
623 {
624   g_return_if_fail (window != NULL);
625   g_return_if_fail (GTK_IS_WINDOW (window));
626   g_return_if_fail (accel_group != NULL);
627
628   gtk_accel_group_attach (accel_group, GTK_OBJECT (window));
629 }
630
631 void
632 gtk_window_remove_accel_group (GtkWindow       *window,
633                                GtkAccelGroup   *accel_group)
634 {
635   g_return_if_fail (window != NULL);
636   g_return_if_fail (GTK_IS_WINDOW (window));
637   g_return_if_fail (accel_group != NULL);
638
639   gtk_accel_group_detach (accel_group, GTK_OBJECT (window));
640 }
641
642 GtkAccelGroup*
643 gtk_window_get_default_accel_group (GtkWindow *window)
644 {
645   GtkAccelGroup *group;
646   
647   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
648
649   group = gtk_object_get_data (GTK_OBJECT (window),
650                                "gtk-accel-group");
651
652   if (group == NULL)
653     {
654       group = gtk_accel_group_new ();
655       gtk_window_add_accel_group (window, group);
656       gtk_object_set_data (GTK_OBJECT (window),
657                            "gtk-accel-group",
658                            group);
659       gtk_accel_group_unref (group);
660     }
661
662   return group;
663 }
664
665 void
666 gtk_window_set_position (GtkWindow         *window,
667                          GtkWindowPosition  position)
668 {
669   g_return_if_fail (window != NULL);
670   g_return_if_fail (GTK_IS_WINDOW (window));
671
672   window->position = position;
673 }
674
675 gint
676 gtk_window_activate_focus (GtkWindow      *window)
677 {
678   g_return_val_if_fail (window != NULL, FALSE);
679   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
680
681   if (window->focus_widget)
682     {
683       if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
684         gtk_widget_activate (window->focus_widget);
685       return TRUE;
686     }
687
688   return FALSE;
689 }
690
691 gint
692 gtk_window_activate_default (GtkWindow      *window)
693 {
694   g_return_val_if_fail (window != NULL, FALSE);
695   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
696
697   if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget))
698     {
699       gtk_widget_activate (window->default_widget);
700       return TRUE;
701     }
702
703   return FALSE;
704 }
705
706 /**
707  * gtk_window_set_modal:
708  * @window: a #GtkWindow
709  * @modal: whether the window is modal
710  * 
711  * Sets a window modal or non-modal. Modal windows prevent interaction
712  * with other windows in the same application. To keep modal dialogs
713  * on top of main application windows, use
714  * gtk_window_set_transient_for() to make the dialog transient for the
715  * parent; most window managers will then disallow lowering the dialog
716  * below the parent.
717  * 
718  * 
719  **/
720 void
721 gtk_window_set_modal (GtkWindow *window,
722                       gboolean   modal)
723 {
724   g_return_if_fail (window != NULL);
725   g_return_if_fail (GTK_IS_WINDOW (window));
726
727   window->modal = modal != FALSE;
728
729   /* adjust desired modality state */
730   if (GTK_WIDGET_VISIBLE (window) && window->modal)
731     gtk_grab_add (GTK_WIDGET (window));
732   else
733     gtk_grab_remove (GTK_WIDGET (window));
734 }
735
736 /**
737  * gtk_window_list_toplevels:
738  * 
739  * Returns a list of all existing toplevel windows. Each widget
740  * in the list has a reference added to it; to free the
741  * list, first unref each widget in the list, then free the list.
742  * 
743  * Return value: list of referenced toplevel widgets
744  **/
745 GList*
746 gtk_window_list_toplevels (void)
747 {
748   GList *list = NULL;
749   GSList *slist;
750
751   for (slist = toplevel_list; slist; slist = slist->next)
752     list = g_list_prepend (list, gtk_widget_ref (slist->data));
753
754   return list;
755 }
756
757 void
758 gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
759 {
760   GList *embedded_windows;
761
762   g_return_if_fail (window != NULL);
763   g_return_if_fail (GTK_IS_WINDOW (window));
764
765   embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
766   if (embedded_windows)
767     gtk_object_remove_no_notify_by_id (GTK_OBJECT (window), 
768                                        g_quark_from_static_string ("gtk-embedded"));
769   embedded_windows = g_list_prepend (embedded_windows,
770                                      GUINT_TO_POINTER (xid));
771
772   gtk_object_set_data_full (GTK_OBJECT (window), "gtk-embedded", 
773                             embedded_windows,
774                             embedded_windows ?
775                               (GtkDestroyNotify) g_list_free : NULL);
776 }
777
778 void
779 gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
780 {
781   GList *embedded_windows;
782   GList *node;
783
784   g_return_if_fail (window != NULL);
785   g_return_if_fail (GTK_IS_WINDOW (window));
786   
787   embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
788   if (embedded_windows)
789     gtk_object_remove_no_notify_by_id (GTK_OBJECT (window), 
790                                        g_quark_from_static_string ("gtk-embedded"));
791
792   node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
793   if (node)
794     {
795       embedded_windows = g_list_remove_link (embedded_windows, node);
796       g_list_free_1 (node);
797     }
798   
799   gtk_object_set_data_full (GTK_OBJECT (window), 
800                             "gtk-embedded", embedded_windows,
801                             embedded_windows ?
802                               (GtkDestroyNotify) g_list_free : NULL);
803 }
804
805 void       
806 gtk_window_reposition (GtkWindow *window,
807                        gint       x,
808                        gint       y)
809 {
810   GtkWindowGeometryInfo *info;
811   
812   g_return_if_fail (window != NULL);
813   g_return_if_fail (GTK_IS_WINDOW (window));
814
815   /* keep this in sync with gtk_window_compute_reposition()
816    */
817   if (GTK_WIDGET_REALIZED (window))
818     {
819       info = gtk_window_get_geometry_info (window, TRUE);
820
821       if (!(info->last.flags & GDK_HINT_POS))
822         {
823           info->last.flags |= GDK_HINT_POS;
824           gdk_window_set_geometry_hints (GTK_WIDGET (window)->window,
825                                          &info->last.geometry,
826                                          info->last.flags);
827         }
828
829       if (window->frame)
830         gdk_window_move (window->frame,  x - window->frame_left, y - window->frame_top);
831       else
832         gdk_window_move (GTK_WIDGET (window)->window, x, y);
833     }
834 }
835
836 static void
837 gtk_window_shutdown (GObject *object)
838 {
839   GtkWindow *window;
840
841   g_return_if_fail (GTK_IS_WINDOW (object));
842
843   window = GTK_WINDOW (object);
844
845   gtk_window_set_focus (window, NULL);
846   gtk_window_set_default (window, NULL);
847
848   G_OBJECT_CLASS (parent_class)->shutdown (object);
849 }
850
851 static void
852 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
853 {
854   gtk_widget_destroy (GTK_WIDGET (child));
855 }
856
857 static void
858 connect_parent_destroyed (GtkWindow *window)
859 {
860   if (window->transient_parent)
861     {
862       gtk_signal_connect (GTK_OBJECT (window->transient_parent),
863                           "destroy",
864                           GTK_SIGNAL_FUNC (parent_destroyed_callback),
865                           window);
866     }  
867 }
868
869 static void
870 disconnect_parent_destroyed (GtkWindow *window)
871 {
872   if (window->transient_parent)
873     {
874       gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
875                                      GTK_SIGNAL_FUNC (parent_destroyed_callback),
876                                      window);
877     }
878 }
879
880 static void
881 gtk_window_transient_parent_realized (GtkWidget *parent,
882                                       GtkWidget *window)
883 {
884   if (GTK_WIDGET_REALIZED (window))
885     gdk_window_set_transient_for (window->window, parent->window);
886 }
887
888 static void
889 gtk_window_transient_parent_unrealized (GtkWidget *parent,
890                                         GtkWidget *window)
891 {
892   if (GTK_WIDGET_REALIZED (window))
893     gdk_property_delete (window->window, 
894                          gdk_atom_intern ("WM_TRANSIENT_FOR", FALSE));
895 }
896
897 static void       
898 gtk_window_unset_transient_for  (GtkWindow *window)
899 {
900   if (window->transient_parent)
901     {
902       gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
903                                      GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
904                                      window);
905       gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
906                                      GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
907                                      window);
908       gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
909                                      GTK_SIGNAL_FUNC (gtk_widget_destroyed),
910                                      &window->transient_parent);
911
912       if (window->destroy_with_parent)
913         disconnect_parent_destroyed (window);
914       
915       window->transient_parent = NULL;
916     }
917 }
918
919 /**
920  * gtk_window_set_transient_for:
921  * @window: a #GtkWindow
922  * @parent: parent window
923  *
924  * Dialog windows should be set transient for the main application
925  * window they were spawned from. This allows window managers to
926  * e.g. keep the dialog on top of the main window, or center the
927  * dialog over the main window. gtk_dialog_new_with_buttons() and
928  * other convenience functions in GTK+ will sometimes call
929  * gtk_window_set_transient_for() on yoru behalf.
930  * 
931  **/
932 void       
933 gtk_window_set_transient_for  (GtkWindow *window, 
934                                GtkWindow *parent)
935 {
936   g_return_if_fail (GTK_IS_WINDOW (window));
937   g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
938   g_return_if_fail (window != parent);
939
940     
941   if (window->transient_parent)
942     {
943       if (GTK_WIDGET_REALIZED (window) && 
944           GTK_WIDGET_REALIZED (window->transient_parent) && 
945           (!parent || !GTK_WIDGET_REALIZED (parent)))
946         gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
947                                                 GTK_WIDGET (window));
948
949       gtk_window_unset_transient_for (window);
950     }
951
952   window->transient_parent = parent;
953
954   if (parent)
955     {
956       gtk_signal_connect (GTK_OBJECT (parent), "destroy",
957                           GTK_SIGNAL_FUNC (gtk_widget_destroyed),
958                           &window->transient_parent);
959       gtk_signal_connect (GTK_OBJECT (parent), "realize",
960                           GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
961                           window);
962       gtk_signal_connect (GTK_OBJECT (parent), "unrealize",
963                           GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
964                           window);
965
966       if (window->destroy_with_parent)
967         connect_parent_destroyed (window);
968       
969       if (GTK_WIDGET_REALIZED (window) &&
970           GTK_WIDGET_REALIZED (parent))
971         gtk_window_transient_parent_realized (GTK_WIDGET (parent),
972                                               GTK_WIDGET (window));
973     }
974 }
975
976 /**
977  * gtk_window_set_destroy_with_parent:
978  * @window: a #GtkWindow
979  * @setting: whether to destroy @window with its transient parent
980  * 
981  * If @setting is TRUE, then destroying the transient parent of @window
982  * will also destroy @window itself. This is useful for dialogs that
983  * shouldn't persist beyond the lifetime of the main window they're
984  * associated with, for example.
985  **/
986 void
987 gtk_window_set_destroy_with_parent  (GtkWindow *window,
988                                      gboolean   setting)
989 {
990   g_return_if_fail (GTK_IS_WINDOW (window));
991
992   if (window->destroy_with_parent == (setting != FALSE))
993     return;
994
995   if (window->destroy_with_parent)
996     {
997       disconnect_parent_destroyed (window);
998     }
999   else
1000     {
1001       connect_parent_destroyed (window);
1002     }
1003   
1004   window->destroy_with_parent = setting;
1005 }
1006
1007 static void
1008 gtk_window_geometry_destroy (GtkWindowGeometryInfo *info)
1009 {
1010   if (info->widget)
1011     gtk_signal_disconnect_by_func (GTK_OBJECT (info->widget),
1012                                    GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1013                                    &info->widget);
1014   g_free (info);
1015 }
1016
1017 static GtkWindowGeometryInfo*
1018 gtk_window_get_geometry_info (GtkWindow *window,
1019                               gboolean   create)
1020 {
1021   GtkWindowGeometryInfo *info;
1022
1023   info = gtk_object_get_data (GTK_OBJECT (window), "gtk-window-geometry");
1024
1025   if (!info && create)
1026     {
1027       info = g_new0 (GtkWindowGeometryInfo, 1);
1028
1029       info->width = 0;
1030       info->height = 0;
1031       info->last.width = -1;
1032       info->last.height = -1;
1033       info->widget = NULL;
1034       info->mask = 0;
1035
1036       gtk_object_set_data_full (GTK_OBJECT (window), 
1037                                 "gtk-window-geometry",
1038                                 info, 
1039                                 (GtkDestroyNotify) gtk_window_geometry_destroy);
1040     }
1041
1042   return info;
1043 }
1044
1045 /**
1046  * gtk_window_set_geometry_hints:
1047  * @window: a #GdkWindow
1048  * @geometry_widget: widget the geometry hints will be applied to
1049  * @geometry: struct containing geometry information
1050  * @geom_mask: mask indicating which struct fields should be paid attention to
1051  *
1052  * This function sets up hints about how a window can be resized by
1053  * the user.  You can set a minimum and maximum size; allowed resize
1054  * increments (e.g. for xterm, you can only resize by the size of a
1055  * character); aspect ratios; and more. See the #GdkGeometry struct.
1056  * 
1057  **/
1058 void       
1059 gtk_window_set_geometry_hints (GtkWindow       *window,
1060                                GtkWidget       *geometry_widget,
1061                                GdkGeometry     *geometry,
1062                                GdkWindowHints   geom_mask)
1063 {
1064   GtkWindowGeometryInfo *info;
1065
1066   g_return_if_fail (window != NULL);
1067
1068   info = gtk_window_get_geometry_info (window, TRUE);
1069   
1070   if (info->widget)
1071     gtk_signal_disconnect_by_func (GTK_OBJECT (info->widget),
1072                                    GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1073                                    &info->widget);
1074   
1075   info->widget = geometry_widget;
1076   if (info->widget)
1077     gtk_signal_connect (GTK_OBJECT (geometry_widget), "destroy",
1078                         GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1079                         &info->widget);
1080
1081   if (geometry)
1082     info->geometry = *geometry;
1083
1084   info->mask = geom_mask;
1085
1086   gtk_widget_queue_resize (GTK_WIDGET (window));
1087 }
1088
1089 /**
1090  * gtk_window_set_default_size:
1091  * @window: a #GtkWindow
1092  * @width: width in pixels, or -1 to leave the default width unchanged
1093  * @height: height in pixels, or -1 to leave the default height unchanged
1094  *
1095  * Sets the default size of a window. If the window's "natural" size
1096  * (its size request) is larger than the default, the default will be
1097  * ignored. So the default size is a minimum initial size.  Unlike
1098  * gtk_widget_set_usize(), which sets a size request for a widget and
1099  * thus would keep users from shrinking the window, this function only
1100  * sets the initial size, just as if the user had resized the window
1101  * themselves. Users can still shrink the window again as they
1102  * normally would.
1103  *
1104  * For more control over a window's initial size and how resizing works,
1105  * investigate gtk_window_set_geometry_hints().
1106  * 
1107  **/
1108 void       
1109 gtk_window_set_default_size (GtkWindow   *window,
1110                              gint         width,
1111                              gint         height)
1112 {
1113   GtkWindowGeometryInfo *info;
1114
1115   g_return_if_fail (GTK_IS_WINDOW (window));
1116
1117   info = gtk_window_get_geometry_info (window, TRUE);
1118
1119   if (width >= 0)
1120     info->width = width;
1121   if (height >= 0)
1122     info->height = height;
1123
1124   gtk_widget_queue_resize (GTK_WIDGET (window));
1125 }
1126   
1127 static void
1128 gtk_window_destroy (GtkObject *object)
1129 {
1130   GtkWindow *window;
1131   
1132   g_return_if_fail (GTK_IS_WINDOW (object));
1133
1134   window = GTK_WINDOW (object);
1135
1136   if (window->transient_parent)
1137     gtk_window_set_transient_for (window, NULL);
1138
1139   if (window->has_user_ref_count)
1140     {
1141       window->has_user_ref_count = FALSE;
1142       gtk_widget_unref (GTK_WIDGET (window));
1143     }
1144
1145   GTK_OBJECT_CLASS (parent_class)->destroy (object);
1146 }
1147
1148 static void
1149 gtk_window_finalize (GObject *object)
1150 {
1151   GtkWindow *window;
1152
1153   g_return_if_fail (GTK_IS_WINDOW (object));
1154
1155   window = GTK_WINDOW (object);
1156
1157   toplevel_list = g_slist_remove (toplevel_list, window);
1158
1159   g_free (window->title);
1160   g_free (window->wmclass_name);
1161   g_free (window->wmclass_class);
1162
1163   G_OBJECT_CLASS(parent_class)->finalize (object);
1164 }
1165
1166 static void
1167 gtk_window_show (GtkWidget *widget)
1168 {
1169   GtkWindow *window = GTK_WINDOW (widget);
1170   GtkContainer *container = GTK_CONTAINER (window);
1171   gboolean need_resize;
1172   gboolean was_realized;
1173   
1174   GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
1175   
1176   need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
1177   container->need_resize = FALSE;
1178   
1179   if (need_resize)
1180     {
1181       GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
1182       GtkAllocation allocation = { 0, 0 };
1183       GdkGeometry new_geometry;
1184       guint width, height, new_flags;
1185       
1186       /* determine default size to initially show the window with */
1187       gtk_widget_size_request (widget, NULL);
1188       gtk_window_compute_default_size (window, &width, &height);
1189       
1190       /* save away the last default size for later comparisions */
1191       info->last.width = width;
1192       info->last.height = height;
1193
1194       /* constrain size to geometry */
1195       gtk_window_compute_hints (window, &new_geometry, &new_flags);
1196       gtk_window_constrain_size (window,
1197                                  &new_geometry, new_flags,
1198                                  width, height,
1199                                  &width, &height);
1200       
1201       /* and allocate the window */
1202       allocation.width  = width;
1203       allocation.height = height;
1204       gtk_widget_size_allocate (widget, &allocation);
1205       
1206       was_realized = FALSE;
1207       if (!GTK_WIDGET_REALIZED (widget))
1208         {
1209           gtk_widget_realize (widget);
1210           was_realized = TRUE;;
1211         }
1212
1213       /* Must be done after the windows are realized,
1214          so that the decorations can be read */
1215       gtk_decorated_window_calculate_frame_size (window);
1216       
1217       if (!was_realized)
1218         gdk_window_resize (widget->window, width, height);
1219     }
1220   
1221   gtk_container_check_resize (container);
1222
1223   gtk_widget_map (widget);
1224
1225   if (window->modal)
1226     gtk_grab_add (widget);
1227 }
1228
1229 static void
1230 gtk_window_hide (GtkWidget *widget)
1231 {
1232   GtkWindow *window;
1233
1234   g_return_if_fail (widget != NULL);
1235   g_return_if_fail (GTK_IS_WINDOW (widget));
1236
1237   window = GTK_WINDOW (widget);
1238
1239   GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
1240   gtk_widget_unmap (widget);
1241
1242   if (window->modal)
1243     gtk_grab_remove (widget);
1244 }
1245
1246 static void
1247 gtk_window_map (GtkWidget *widget)
1248 {
1249   GtkWindow *window;
1250   GdkWindow *toplevel;
1251   
1252   g_return_if_fail (widget != NULL);
1253   g_return_if_fail (GTK_IS_WINDOW (widget));
1254
1255   GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
1256
1257   window = GTK_WINDOW (widget);
1258
1259   if (window->bin.child &&
1260       GTK_WIDGET_VISIBLE (window->bin.child) &&
1261       !GTK_WIDGET_MAPPED (window->bin.child))
1262     gtk_widget_map (window->bin.child);
1263
1264   if (window->frame)
1265     toplevel = window->frame;
1266   else
1267     toplevel = widget->window;
1268   
1269   if (window->maximize_initially)
1270     gdk_window_maximize (toplevel);
1271   else
1272     gdk_window_unmaximize (toplevel);
1273   
1274   if (window->stick_initially)
1275     gdk_window_stick (toplevel);
1276   else
1277     gdk_window_unstick (toplevel);
1278   
1279   if (window->iconify_initially)
1280     gdk_window_iconify (toplevel);
1281   else
1282     gdk_window_deiconify (toplevel);
1283   
1284   gdk_window_show (widget->window);
1285
1286   if (window->frame)
1287     gdk_window_show (window->frame);
1288 }
1289
1290 static void
1291 gtk_window_unmap (GtkWidget *widget)
1292 {
1293   GtkWindow *window;
1294
1295   g_return_if_fail (widget != NULL);
1296   g_return_if_fail (GTK_IS_WINDOW (widget));
1297
1298   window = GTK_WINDOW (widget);
1299   
1300   GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1301   if (window->frame)
1302     gdk_window_withdraw (window->frame);
1303   else 
1304     gdk_window_withdraw (widget->window);
1305
1306   window->use_uposition = TRUE;
1307   window->resize_count = 0;
1308   window->handling_resize = FALSE;
1309
1310 }
1311
1312 static void
1313 gtk_window_realize (GtkWidget *widget)
1314 {
1315   GtkWindow *window;
1316   GdkWindow *parent_window;
1317   GdkWindowAttr attributes;
1318   gint attributes_mask;
1319   
1320   g_return_if_fail (GTK_IS_WINDOW (widget));
1321
1322   window = GTK_WINDOW (widget);
1323
1324   /* ensure widget tree is properly size allocated */
1325   if (widget->allocation.x == -1 &&
1326       widget->allocation.y == -1 &&
1327       widget->allocation.width == 1 &&
1328       widget->allocation.height == 1)
1329     {
1330       GtkRequisition requisition;
1331       GtkAllocation allocation = { 0, 0, 200, 200 };
1332
1333       gtk_widget_size_request (widget, &requisition);
1334       if (requisition.width || requisition.height)
1335         {
1336           /* non-empty window */
1337           allocation.width = requisition.width;
1338           allocation.height = requisition.height;
1339         }
1340       gtk_widget_size_allocate (widget, &allocation);
1341       
1342       gtk_container_queue_resize (GTK_CONTAINER (widget));
1343
1344       g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
1345     }
1346   
1347   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
1348   
1349   switch (window->type)
1350     {
1351     case GTK_WINDOW_TOPLEVEL:
1352       attributes.window_type = GDK_WINDOW_TOPLEVEL;
1353       break;
1354     case GTK_WINDOW_DIALOG:
1355       attributes.window_type = GDK_WINDOW_DIALOG;
1356       break;
1357     case GTK_WINDOW_POPUP:
1358       attributes.window_type = GDK_WINDOW_TEMP;
1359       break;
1360     }
1361    
1362   attributes.title = window->title;
1363   attributes.wmclass_name = window->wmclass_name;
1364   attributes.wmclass_class = window->wmclass_class;
1365   attributes.wclass = GDK_INPUT_OUTPUT;
1366   attributes.visual = gtk_widget_get_visual (widget);
1367   attributes.colormap = gtk_widget_get_colormap (widget);
1368
1369   if (window->has_frame)
1370     {
1371       attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
1372       attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
1373       attributes.event_mask = (GDK_EXPOSURE_MASK |
1374                                GDK_KEY_PRESS_MASK |
1375                                GDK_ENTER_NOTIFY_MASK |
1376                                GDK_LEAVE_NOTIFY_MASK |
1377                                GDK_FOCUS_CHANGE_MASK |
1378                                GDK_STRUCTURE_MASK |
1379                                GDK_BUTTON_MOTION_MASK |
1380                                GDK_POINTER_MOTION_HINT_MASK |
1381                                GDK_BUTTON_PRESS_MASK |
1382                                GDK_BUTTON_RELEASE_MASK);
1383       
1384       attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
1385       
1386       window->frame = gdk_window_new (NULL, &attributes, attributes_mask);
1387       gdk_window_set_user_data (window->frame, widget);
1388       
1389       attributes.window_type = GDK_WINDOW_CHILD;
1390       attributes.x = window->frame_left;
1391       attributes.y = window->frame_right;
1392     
1393       attributes_mask = GDK_WA_X | GDK_WA_Y;
1394
1395       parent_window = window->frame;
1396     }
1397   else
1398     {
1399       attributes_mask = 0;
1400       parent_window = NULL;
1401     }
1402   
1403   attributes.width = widget->allocation.width;
1404   attributes.height = widget->allocation.height;
1405   attributes.event_mask = gtk_widget_get_events (widget);
1406   attributes.event_mask |= (GDK_EXPOSURE_MASK |
1407                             GDK_KEY_PRESS_MASK |
1408                             GDK_ENTER_NOTIFY_MASK |
1409                             GDK_LEAVE_NOTIFY_MASK |
1410                             GDK_FOCUS_CHANGE_MASK |
1411                             GDK_STRUCTURE_MASK);
1412
1413   attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
1414   attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
1415   attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
1416   widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
1417   gdk_window_set_user_data (widget->window, window);
1418       
1419   widget->style = gtk_style_attach (widget->style, widget->window);
1420   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
1421   if (window->frame)
1422     gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
1423
1424   /* This is a bad hack to set the window background. */
1425   gtk_window_paint (widget, NULL);
1426   
1427   if (window->transient_parent &&
1428       GTK_WIDGET_REALIZED (window->transient_parent))
1429     gdk_window_set_transient_for (widget->window,
1430                                   GTK_WIDGET (window->transient_parent)->window);
1431 }
1432
1433 static void
1434 gtk_window_unrealize (GtkWidget *widget)
1435 {
1436   GtkWindow *window;
1437
1438   g_return_if_fail (widget != NULL);
1439   g_return_if_fail (GTK_IS_WINDOW (widget));
1440
1441   window = GTK_WINDOW (widget);
1442
1443   if (window->frame)
1444     {
1445       gdk_window_set_user_data (window->frame, NULL);
1446       gdk_window_destroy (window->frame);
1447       window->frame = NULL;
1448     }
1449   
1450   (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
1451 }
1452
1453 static void
1454 gtk_window_size_request (GtkWidget      *widget,
1455                          GtkRequisition *requisition)
1456 {
1457   GtkWindow *window;
1458   GtkBin *bin;
1459
1460   g_return_if_fail (widget != NULL);
1461   g_return_if_fail (GTK_IS_WINDOW (widget));
1462   g_return_if_fail (requisition != NULL);
1463
1464   window = GTK_WINDOW (widget);
1465   bin = GTK_BIN (window);
1466   
1467   requisition->width = GTK_CONTAINER (window)->border_width * 2;
1468   requisition->height = GTK_CONTAINER (window)->border_width * 2;
1469
1470   if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
1471     {
1472       GtkRequisition child_requisition;
1473       
1474       gtk_widget_size_request (bin->child, &child_requisition);
1475
1476       requisition->width += child_requisition.width;
1477       requisition->height += child_requisition.height;
1478     }
1479 }
1480
1481 static void
1482 gtk_window_size_allocate (GtkWidget     *widget,
1483                           GtkAllocation *allocation)
1484 {
1485   GtkWindow *window;
1486   GtkAllocation child_allocation;
1487
1488   g_return_if_fail (widget != NULL);
1489   g_return_if_fail (GTK_IS_WINDOW (widget));
1490   g_return_if_fail (allocation != NULL);
1491
1492   window = GTK_WINDOW (widget);
1493   widget->allocation = *allocation;
1494
1495   if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
1496     {
1497       child_allocation.x = GTK_CONTAINER (window)->border_width;
1498       child_allocation.y = GTK_CONTAINER (window)->border_width;
1499       child_allocation.width =
1500         MAX (1, (gint)allocation->width - child_allocation.x * 2);
1501       child_allocation.height =
1502         MAX (1, (gint)allocation->height - child_allocation.y * 2);
1503
1504       gtk_widget_size_allocate (window->bin.child, &child_allocation);
1505     }
1506
1507   if (GTK_WIDGET_REALIZED (widget) && window->frame)
1508     {
1509       gdk_window_resize (window->frame,
1510                          allocation->width + window->frame_left + window->frame_right,
1511                          allocation->height + window->frame_top + window->frame_bottom);
1512     }
1513 }
1514
1515 static gint
1516 gtk_window_event (GtkWidget *widget, GdkEvent *event)
1517 {
1518   GtkWindow *window;
1519   gboolean return_val;
1520
1521   
1522   g_return_val_if_fail (widget != NULL, FALSE);
1523   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1524   g_return_val_if_fail (event != NULL, FALSE);
1525   
1526   window = GTK_WINDOW (widget);
1527
1528   if (window->frame && (event->any.window == window->frame))
1529     {
1530       if ((event->type != GDK_KEY_PRESS) &&
1531           (event->type != GDK_KEY_RELEASE) &&
1532           (event->type != GDK_FOCUS_CHANGE))
1533         {
1534           gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "event");
1535           return_val = FALSE;
1536           gtk_signal_emit (GTK_OBJECT (widget), window_signals[FRAME_EVENT], event, &return_val);
1537           return TRUE;
1538         }
1539       else
1540         {
1541           g_object_unref (event->any.window);
1542           event->any.window = g_object_ref (widget->window);
1543         }
1544     }
1545
1546   return FALSE;
1547 }
1548
1549 static gboolean
1550 gtk_window_frame_event (GtkWidget *widget, GdkEvent *event)
1551 {
1552   GdkEventConfigure *configure_event;
1553   GtkWindow *window = GTK_WINDOW (widget);
1554   GdkRectangle rect;
1555
1556   switch (event->type)
1557     {
1558     case GDK_CONFIGURE:
1559       configure_event = (GdkEventConfigure *)event;
1560       
1561       /* Invalidate the decorations */
1562       rect.x = 0;
1563       rect.y = 0;
1564       rect.width = configure_event->width;
1565       rect.height = configure_event->height;
1566       
1567       gdk_window_invalidate_rect (window->frame, &rect, FALSE);
1568
1569       /* Pass on the (modified) configure event */
1570       configure_event->width -= window->frame_left + window->frame_right;
1571       configure_event->height -= window->frame_top + window->frame_bottom;
1572       return gtk_window_configure_event (widget, configure_event);
1573       break;
1574     default:
1575       break;
1576     }
1577   return FALSE;
1578 }
1579
1580 static gint
1581 gtk_window_configure_event (GtkWidget         *widget,
1582                             GdkEventConfigure *event)
1583 {
1584   GtkWindow *window;
1585   
1586   g_return_val_if_fail (widget != NULL, FALSE);
1587   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1588   g_return_val_if_fail (event != NULL, FALSE);
1589   
1590   window = GTK_WINDOW (widget);
1591
1592   /* we got a configure event specifying the new window size and position,
1593    * in principle we have to distinguish 4 cases here:
1594    * 1) the size didn't change and resize_count == 0
1595    *    -> the window was merely moved (sometimes not even that)
1596    * 2) the size didn't change and resize_count > 0
1597    *    -> we requested a new size, but didn't get it
1598    * 3) the size changed and resize_count > 0
1599    *    -> we asked for a new size and we got one
1600    * 4) the size changed and resize_count == 0
1601    *    -> we got resized from outside the toolkit, and have to
1602    *    accept that size since we don't want to fight neither the
1603    *    window manager nor the user
1604    * in the three latter cases we have to reallocate the widget tree,
1605    * which happens in gtk_window_move_resize(), so we set a flag for
1606    * that function and assign the new size. if resize_count > 1,
1607    * we simply do nothing and wait for more configure events.
1608    */
1609
1610   if (window->resize_count > 0 ||
1611       widget->allocation.width != event->width ||
1612       widget->allocation.height != event->height)
1613     {
1614       if (window->resize_count > 0)
1615         window->resize_count -= 1;
1616
1617       if (window->resize_count == 0)
1618         {
1619           window->handling_resize = TRUE;
1620           
1621           widget->allocation.width = event->width;
1622           widget->allocation.height = event->height;
1623           
1624           gtk_widget_queue_resize (widget);
1625         }
1626     }
1627
1628   return TRUE;
1629 }
1630
1631 static gint
1632 gtk_window_key_press_event (GtkWidget   *widget,
1633                             GdkEventKey *event)
1634 {
1635   GtkWindow *window;
1636   GtkDirectionType direction = 0;
1637   gboolean handled;
1638
1639   g_return_val_if_fail (widget != NULL, FALSE);
1640   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1641   g_return_val_if_fail (event != NULL, FALSE);
1642
1643   window = GTK_WINDOW (widget);
1644
1645   handled = FALSE;
1646   
1647   if (window->focus_widget &&
1648       window->focus_widget != widget &&
1649       GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1650     {
1651       handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
1652     }
1653     
1654   if (!handled)
1655     handled = gtk_accel_groups_activate (GTK_OBJECT (window), event->keyval, event->state);
1656
1657   if (!handled)
1658     {
1659       switch (event->keyval)
1660         {
1661         case GDK_space:
1662           if (window->focus_widget)
1663             {
1664               if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1665                 gtk_widget_activate (window->focus_widget);
1666               handled = TRUE;
1667             }
1668           break;
1669         case GDK_Return:
1670         case GDK_KP_Enter:
1671           if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
1672               (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1673             {
1674               gtk_widget_activate (window->default_widget);
1675               handled = TRUE;
1676             }
1677           else if (window->focus_widget)
1678             {
1679               if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1680                 gtk_widget_activate (window->focus_widget);
1681               handled = TRUE;
1682             }
1683           break;
1684         case GDK_Up:
1685         case GDK_Down:
1686         case GDK_Left:
1687         case GDK_Right:
1688         case GDK_KP_Up:
1689         case GDK_KP_Down:
1690         case GDK_KP_Left:
1691         case GDK_KP_Right:
1692         case GDK_Tab:
1693         case GDK_ISO_Left_Tab:
1694           switch (event->keyval)
1695             {
1696             case GDK_Up:
1697             case GDK_KP_Up:
1698               direction = GTK_DIR_UP;
1699               break;
1700             case GDK_Down:
1701             case GDK_KP_Down:
1702               direction = GTK_DIR_DOWN;
1703               break;
1704             case GDK_Left:
1705             case GDK_KP_Left:
1706               direction = GTK_DIR_LEFT;
1707               break;
1708             case GDK_Right:
1709             case GDK_KP_Right:
1710               direction = GTK_DIR_RIGHT;
1711               break;
1712             case GDK_Tab:
1713             case GDK_ISO_Left_Tab:
1714               if (event->state & GDK_SHIFT_MASK)
1715                 direction = GTK_DIR_TAB_BACKWARD;
1716               else
1717                 direction = GTK_DIR_TAB_FORWARD;
1718               break;
1719             default :
1720               direction = GTK_DIR_UP; /* never reached, but makes compiler happy */
1721             }
1722
1723           gtk_container_focus (GTK_CONTAINER (widget), direction);
1724
1725           if (!GTK_CONTAINER (window)->focus_child)
1726             gtk_window_set_focus (GTK_WINDOW (widget), NULL);
1727           else
1728             handled = TRUE;
1729           break;
1730         }
1731     }
1732
1733   if (!handled && GTK_WIDGET_CLASS (parent_class)->key_press_event)
1734     handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
1735
1736   return handled;
1737 }
1738
1739 static gint
1740 gtk_window_key_release_event (GtkWidget   *widget,
1741                               GdkEventKey *event)
1742 {
1743   GtkWindow *window;
1744   gint handled;
1745   
1746   g_return_val_if_fail (widget != NULL, FALSE);
1747   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1748   g_return_val_if_fail (event != NULL, FALSE);
1749   
1750   window = GTK_WINDOW (widget);
1751   handled = FALSE;
1752   if (window->focus_widget &&
1753       window->focus_widget != widget &&
1754       GTK_WIDGET_SENSITIVE (window->focus_widget))
1755     {
1756       handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
1757     }
1758
1759   if (!handled && GTK_WIDGET_CLASS (parent_class)->key_release_event)
1760     handled = GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
1761
1762   return handled;
1763 }
1764
1765 static gint
1766 gtk_window_enter_notify_event (GtkWidget        *widget,
1767                                GdkEventCrossing *event)
1768 {
1769   g_return_val_if_fail (widget != NULL, FALSE);
1770   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1771   g_return_val_if_fail (event != NULL, FALSE);
1772
1773   return FALSE;
1774 }
1775
1776 static gint
1777 gtk_window_leave_notify_event (GtkWidget        *widget,
1778                                GdkEventCrossing *event)
1779 {
1780   g_return_val_if_fail (widget != NULL, FALSE);
1781   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1782   g_return_val_if_fail (event != NULL, FALSE);
1783
1784   return FALSE;
1785 }
1786
1787 static gint
1788 gtk_window_focus_in_event (GtkWidget     *widget,
1789                            GdkEventFocus *event)
1790 {
1791   GtkWindow *window;
1792   GdkEventFocus fevent;
1793
1794   g_return_val_if_fail (widget != NULL, FALSE);
1795   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1796   g_return_val_if_fail (event != NULL, FALSE);
1797
1798   /* It appears spurious focus in events can occur when
1799    *  the window is hidden. So we'll just check to see if
1800    *  the window is visible before actually handling the
1801    *  event
1802    */
1803   if (GTK_WIDGET_VISIBLE (widget))
1804     {
1805       window = GTK_WINDOW (widget);
1806       if (window->focus_widget &&
1807           window->focus_widget != widget &&
1808           !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
1809         {
1810           fevent.type = GDK_FOCUS_CHANGE;
1811           fevent.window = window->focus_widget->window;
1812           fevent.in = TRUE;
1813
1814           gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
1815         }
1816     }
1817
1818   return FALSE;
1819 }
1820
1821 static gint
1822 gtk_window_focus_out_event (GtkWidget     *widget,
1823                             GdkEventFocus *event)
1824 {
1825   GtkWindow *window;
1826   GdkEventFocus fevent;
1827
1828   g_return_val_if_fail (widget != NULL, FALSE);
1829   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1830   g_return_val_if_fail (event != NULL, FALSE);
1831
1832   window = GTK_WINDOW (widget);
1833   if (window->focus_widget &&
1834       window->focus_widget != widget &&
1835       GTK_WIDGET_HAS_FOCUS (window->focus_widget))
1836     {
1837       fevent.type = GDK_FOCUS_CHANGE;
1838       fevent.window = window->focus_widget->window;
1839       fevent.in = FALSE;
1840
1841       gtk_widget_event (window->focus_widget, (GdkEvent*) &fevent);
1842     }
1843
1844   return FALSE;
1845 }
1846
1847 static GdkAtom atom_rcfiles = GDK_NONE;
1848
1849 static void
1850 gtk_window_read_rcfiles (GtkWidget *widget,
1851                          GdkEventClient *event)
1852 {
1853   GList *embedded_windows;
1854
1855   embedded_windows = gtk_object_get_data (GTK_OBJECT (widget), "gtk-embedded");
1856   if (embedded_windows)
1857     {
1858       GdkEventClient sev;
1859       int i;
1860       
1861       for(i = 0; i < 5; i++)
1862         sev.data.l[i] = 0;
1863       sev.data_format = 32;
1864       sev.message_type = atom_rcfiles;
1865       
1866       while (embedded_windows)
1867         {
1868           guint xid = GPOINTER_TO_UINT (embedded_windows->data);
1869           gdk_event_send_client_message ((GdkEvent *) &sev, xid);
1870           embedded_windows = embedded_windows->next;
1871         }
1872     }
1873
1874   if (gtk_rc_reparse_all ())
1875     {
1876       /* If the above returned true, some of our RC files are out
1877        * of date, so we need to reset all our widgets. Our other
1878        * toplevel windows will also get the message, but by
1879        * then, the RC file will up to date, so we have to tell
1880        * them now. Also, we have to invalidate cached icons in
1881        * icon sets so they get re-rendered.
1882        */
1883       GList *list, *toplevels;
1884
1885       _gtk_icon_set_invalidate_caches ();
1886       
1887       toplevels = gtk_window_list_toplevels ();
1888       
1889       for (list = toplevels; list; list = list->next)
1890         {
1891           gtk_widget_reset_rc_styles (list->data);
1892           gtk_widget_unref (list->data);
1893         }
1894       g_list_free (toplevels);
1895     }
1896 }
1897
1898 static gint
1899 gtk_window_client_event (GtkWidget      *widget,
1900                          GdkEventClient *event)
1901 {
1902   g_return_val_if_fail (widget != NULL, FALSE);
1903   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
1904   g_return_val_if_fail (event != NULL, FALSE);
1905
1906   if (!atom_rcfiles)
1907     atom_rcfiles = gdk_atom_intern("_GTK_READ_RCFILES", FALSE);
1908
1909   if(event->message_type == atom_rcfiles) 
1910     gtk_window_read_rcfiles (widget, event);    
1911
1912   return FALSE;
1913 }
1914
1915 static void
1916 gtk_window_check_resize (GtkContainer *container)
1917 {
1918   GtkWindow *window;
1919
1920   g_return_if_fail (container != NULL);
1921   g_return_if_fail (GTK_IS_WINDOW (container));
1922
1923   window = GTK_WINDOW (container);
1924
1925   if (GTK_WIDGET_VISIBLE (container))
1926     gtk_window_move_resize (window);
1927 }
1928
1929 static gboolean
1930 gtk_window_focus (GtkContainer     *container,
1931                   GtkDirectionType  direction)
1932 {
1933   GtkBin *bin = GTK_BIN (container);
1934   GtkWindow *window = GTK_WINDOW (container);
1935   GtkWidget *old_focus_child = container->focus_child;
1936   GtkWidget *parent;
1937   
1938   /* We need a special implementation here to deal properly with wrapping
1939    * around in the tab chain without the danger of going into an
1940    * infinite loop.
1941    */
1942   if (old_focus_child)
1943     {
1944       if (GTK_IS_CONTAINER (old_focus_child) &&
1945           GTK_WIDGET_DRAWABLE (old_focus_child) &&
1946           GTK_WIDGET_IS_SENSITIVE (old_focus_child) &&
1947           gtk_container_focus (GTK_CONTAINER (old_focus_child), direction))
1948         return TRUE;
1949     }
1950
1951   if (window->focus_widget)
1952     {
1953       /* Wrapped off the end, clear the focus setting for the toplpevel */
1954       parent = window->focus_widget->parent;
1955       while (parent)
1956         {
1957           gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
1958           parent = GTK_WIDGET (parent)->parent;
1959         }
1960       
1961       gtk_window_set_focus (GTK_WINDOW (container), NULL);
1962     }
1963
1964   /* Now try to focus the first widget in the window */
1965   if (GTK_WIDGET_DRAWABLE (bin->child) &&
1966       GTK_WIDGET_IS_SENSITIVE (bin->child))
1967     {
1968       if (GTK_IS_CONTAINER (bin->child))
1969         {
1970           if (gtk_container_focus (GTK_CONTAINER (bin->child), direction))
1971             return TRUE;
1972         }
1973       else if (GTK_WIDGET_CAN_FOCUS (bin->child))
1974         {
1975           gtk_widget_grab_focus (bin->child);
1976           return TRUE;
1977         }
1978     }
1979
1980   return FALSE;
1981 }
1982
1983 static void
1984 gtk_window_real_set_focus (GtkWindow *window,
1985                            GtkWidget *focus)
1986 {
1987   GdkEventFocus event;
1988   gboolean def_flags = 0;
1989
1990   g_return_if_fail (window != NULL);
1991   g_return_if_fail (GTK_IS_WINDOW (window));
1992   
1993   if (window->default_widget)
1994     def_flags = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
1995   
1996   if (window->focus_widget)
1997     {
1998       event.type = GDK_FOCUS_CHANGE;
1999       event.window = window->focus_widget->window;
2000       event.in = FALSE;
2001       
2002       if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
2003           (window->focus_widget != window->default_widget))
2004         {
2005           GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
2006           /* if any widget had the default set there should be
2007              a default_widget, but might not so this is a sanity
2008              check */
2009           if (window->default_widget)
2010             GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
2011         }
2012         
2013       gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
2014     }
2015   
2016   window->focus_widget = focus;
2017   
2018   if (window->focus_widget)
2019     {
2020       event.type = GDK_FOCUS_CHANGE;
2021       event.window = window->focus_widget->window;
2022       event.in = TRUE;
2023
2024       if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
2025           (window->focus_widget != window->default_widget))
2026         {
2027           if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
2028             GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
2029
2030           if (window->default_widget)
2031             GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
2032         }
2033       
2034       gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
2035     }
2036   
2037   if (window->default_widget &&
2038       (def_flags != GTK_WIDGET_FLAGS (window->default_widget)))
2039     gtk_widget_queue_draw (window->default_widget);
2040 }
2041
2042 /*********************************
2043  * Functions related to resizing *
2044  *********************************/
2045
2046 static void
2047 gtk_window_move_resize (GtkWindow *window)
2048 {
2049   GtkWidget *widget;
2050   GtkContainer *container;
2051   GtkWindowGeometryInfo *info;
2052   GtkWindowLastGeometryInfo saved_last_info;
2053   GdkGeometry new_geometry;
2054   guint new_flags;
2055   gint x, y;
2056   gint width, height;
2057   gint new_width, new_height;
2058   gboolean default_size_changed = FALSE;
2059   gboolean hints_changed = FALSE;
2060
2061   g_return_if_fail (GTK_IS_WINDOW (window));
2062   g_return_if_fail (GTK_WIDGET_REALIZED (window));
2063
2064   widget = GTK_WIDGET (window);
2065   container = GTK_CONTAINER (widget);
2066   info = gtk_window_get_geometry_info (window, TRUE);
2067   saved_last_info = info->last;
2068
2069   gtk_widget_size_request (widget, NULL);
2070   gtk_window_compute_default_size (window, &new_width, &new_height);
2071   
2072   if (info->last.width < 0 ||
2073       info->last.width != new_width ||
2074       info->last.height != new_height)
2075     {
2076       default_size_changed = TRUE;
2077       info->last.width = new_width;
2078       info->last.height = new_height;
2079
2080       /* We need to force a reposition in this case
2081        */
2082       if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
2083         window->use_uposition = TRUE;
2084     }
2085   
2086   /* Compute new set of hints for the window
2087    */
2088   gtk_window_compute_hints (window, &new_geometry, &new_flags);
2089   if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
2090                                  &new_geometry, new_flags))
2091     {
2092       hints_changed = TRUE;
2093       info->last.geometry = new_geometry;
2094       info->last.flags = new_flags;
2095     }
2096
2097   /* From the default size and the allocation, figure out the size
2098    * the window should be.
2099    */
2100   if (!default_size_changed ||
2101       (!window->auto_shrink &&
2102        new_width <= widget->allocation.width &&
2103        new_height <= widget->allocation.height))
2104     {
2105       new_width = widget->allocation.width;
2106       new_height = widget->allocation.height;
2107     }
2108
2109   /* constrain the window size to the specified geometry */
2110   gtk_window_constrain_size (window,
2111                              &new_geometry, new_flags,
2112                              new_width, new_height,
2113                              &new_width, &new_height);
2114
2115   /* compute new window position if a move is required
2116    */
2117   gtk_window_compute_reposition (window, new_width, new_height, &x, &y);
2118   if (x != 1 && y != -1 && !(new_flags & GDK_HINT_POS))
2119     {
2120       new_flags |= GDK_HINT_POS;
2121       hints_changed = TRUE;
2122     }
2123
2124
2125   /* handle actual resizing:
2126    * - handle reallocations due to configure events
2127    * - figure whether we need to request a new window size
2128    * - handle simple resizes within our widget tree
2129    * - reposition window if neccessary
2130    */
2131   width = widget->allocation.width;
2132   height = widget->allocation.height;
2133
2134   if (window->handling_resize)
2135     { 
2136       GtkAllocation allocation;
2137       
2138       /* if we are just responding to a configure event, which
2139        * might be due to a resize by the window manager, the
2140        * user, or a response to a resizing request we made
2141        * earlier, we go ahead, allocate the new size and we're done
2142        * (see gtk_window_configure_event() for more details).
2143        */
2144       
2145       window->handling_resize = FALSE;
2146       
2147       allocation = widget->allocation;
2148       
2149       gtk_widget_size_allocate (widget, &allocation);
2150       gtk_widget_queue_draw (widget);
2151
2152 #ifdef FIXME_ZVT_ME_HARDER
2153       if ((default_size_changed || hints_changed) && (width != new_width || height != new_height))
2154         {
2155           /* We could be here for two reasons
2156            *  1) We coincidentally got a resize while handling
2157            *     another resize.
2158            *  2) Our computation of default_size_changed was completely
2159            *     screwed up, probably because one of our children
2160            *     is broken (i.e. changes requisition during
2161            *     size allocation). It's probably a zvt widget.
2162            *
2163            * For 1), we could just go ahead and ask for the
2164            * new size right now, but doing that for 2)
2165            * might well be fighting the user (and can even
2166            * trigger a loop). Since we really don't want to
2167            * do that, we requeue a resize in hopes that
2168            * by the time it gets handled, the child has seen
2169            * the light and is willing to go along with the
2170            * new size. (this happens for the zvt widget, since
2171            * the size_allocate() above will have stored the
2172            * requisition corresponding to the new size in the
2173            * zvt widget)
2174            *
2175            * This doesn't buy us anything for 1), but it shouldn't
2176            * hurt us too badly, since it is what would have
2177            * happened if we had gotten the configure event before
2178            * the new size had been set.
2179            */
2180           
2181           if (x != -1 && y != -1)
2182             {
2183               if (window->frame)
2184                 gdk_window_move (window->frame, x - window->frame_left, y - window->frame_top);
2185               else
2186                 gdk_window_move (GTK_WIDGET (window)->window, x, y);
2187             }
2188
2189           /* we have to preserve the values and flags that are used
2190            * for computation of default_size_changed and hints_changed
2191            */
2192
2193           info->last = saved_last_info;
2194           
2195           gtk_widget_queue_resize (widget);
2196
2197           return;
2198         }
2199 #endif /* FIXME_ZVT_ME_HARDER */
2200     }
2201
2202   /* Now set hints if necessary
2203    */
2204   if (hints_changed)
2205     gdk_window_set_geometry_hints (widget->window,
2206                                    &new_geometry,
2207                                    new_flags);
2208
2209   if ((default_size_changed || hints_changed) &&
2210       (width != new_width || height != new_height))
2211     {
2212       /* given that (width != new_width || height != new_height), we are in one
2213        * of the following situations:
2214        * 
2215        * default_size_changed
2216        *   our requisition has changed and we need a different window size,
2217        *   so we request it from the window manager.
2218        *
2219        * !default_size_changed
2220        *   the window manager wouldn't assign us the size we requested, in this
2221        *   case we don't try to request a new size with every resize.
2222        *
2223        * !default_size_changed && hints_changed
2224        *   the window manager rejects our size, but we have just changed the
2225        *   window manager hints, so there's a certain chance our request will
2226        *   be honoured this time, so we try again.
2227        */
2228       
2229       /* request a new window size */
2230       if (x != -1 && y != -1)
2231         {
2232           if (window->frame)
2233             {
2234               gdk_window_move_resize (window->frame,
2235                                       x - window->frame_left, y - window->frame_top,
2236                                       new_width + window->frame_left + window->frame_right,
2237                                       new_height + window->frame_top + window->frame_bottom);
2238               gdk_window_resize (GTK_WIDGET (window)->window, new_width, new_height);
2239             }
2240           else
2241             gdk_window_move_resize (GTK_WIDGET (window)->window, x, y, new_width, new_height);
2242         }
2243       else
2244         {
2245           if (window->frame)
2246             gdk_window_resize (window->frame,
2247                                new_width + window->frame_left + window->frame_right,
2248                                new_height + window->frame_top + window->frame_bottom);
2249           gdk_window_resize (GTK_WIDGET (window)->window, new_width, new_height);
2250         }
2251       window->resize_count += 1;
2252       
2253       /* we are now awaiting the new configure event in response to our
2254        * resizing request. the configure event will cause a new resize
2255        * with ->handling_resize=TRUE.
2256        * until then, we want to
2257        * - discard expose events
2258        * - coalesce resizes for our children
2259        * - defer any window resizes until the configure event arrived
2260        * to achive this, we queue a resize for the window, but remove its
2261        * resizing handler, so resizing will not be handled from the next
2262        * idle handler but when the configure event arrives.
2263        *
2264        * FIXME: we should also dequeue the pending redraws here, since
2265        * we handle those ourselves in ->handling_resize==TRUE.
2266        */
2267       gtk_widget_queue_resize (GTK_WIDGET (container));
2268       if (container->resize_mode == GTK_RESIZE_QUEUE)
2269         gtk_container_dequeue_resize_handler (container);
2270     }
2271   else
2272     {
2273       if (x != -1 && y != -1)
2274         {
2275           if (window->frame)
2276             gdk_window_move (window->frame, x - window->frame_left, y - window->frame_top);
2277           else
2278             gdk_window_move (widget->window, x, y);
2279         }
2280
2281       if (container->resize_widgets)
2282         gtk_container_resize_children (GTK_CONTAINER (window));
2283     }
2284 }
2285
2286 /* Compare two sets of Geometry hints for equality.
2287  */
2288 static gboolean
2289 gtk_window_compare_hints (GdkGeometry *geometry_a,
2290                           guint        flags_a,
2291                           GdkGeometry *geometry_b,
2292                           guint        flags_b)
2293 {
2294   if (flags_a != flags_b)
2295     return FALSE;
2296   
2297   if ((flags_a & GDK_HINT_MIN_SIZE) &&
2298       (geometry_a->min_width != geometry_b->min_width ||
2299        geometry_a->min_height != geometry_b->min_height))
2300     return FALSE;
2301
2302   if ((flags_a & GDK_HINT_MAX_SIZE) &&
2303       (geometry_a->max_width != geometry_b->max_width ||
2304        geometry_a->max_height != geometry_b->max_height))
2305     return FALSE;
2306
2307   if ((flags_a & GDK_HINT_BASE_SIZE) &&
2308       (geometry_a->base_width != geometry_b->base_width ||
2309        geometry_a->base_height != geometry_b->base_height))
2310     return FALSE;
2311
2312   if ((flags_a & GDK_HINT_ASPECT) &&
2313       (geometry_a->min_aspect != geometry_b->min_aspect ||
2314        geometry_a->max_aspect != geometry_b->max_aspect))
2315     return FALSE;
2316
2317   if ((flags_a & GDK_HINT_RESIZE_INC) &&
2318       (geometry_a->width_inc != geometry_b->width_inc ||
2319        geometry_a->height_inc != geometry_b->height_inc))
2320     return FALSE;
2321
2322   return TRUE;
2323 }
2324
2325 /* Compute the default_size for a window. The result will
2326  * be stored in *width and *height. The default size is
2327  * the size the window should have when initially mapped.
2328  * This routine does not attempt to constrain the size
2329  * to obey the geometry hints - that must be done elsewhere.
2330  */
2331 static void 
2332 gtk_window_compute_default_size (GtkWindow       *window,
2333                                  guint           *width,
2334                                  guint           *height)
2335 {
2336   GtkRequisition requisition;
2337   GtkWindowGeometryInfo *info;
2338   
2339   gtk_widget_get_child_requisition (GTK_WIDGET (window), &requisition);
2340   *width = requisition.width;
2341   *height = requisition.height;
2342
2343   info = gtk_window_get_geometry_info (window, FALSE);
2344   
2345   if (*width == 0 && *height == 0)
2346     {
2347       /* empty window */
2348       *width = 200;
2349       *height = 200;
2350     }
2351   
2352   if (info)
2353     {
2354       *width = info->width > 0 ? info->width : *width;
2355       *height = info->height > 0 ? info->height : *height;
2356     }
2357 }
2358
2359 void
2360 _gtk_window_constrain_size (GtkWindow   *window,
2361                             gint         width,
2362                             gint         height,
2363                             gint        *new_width,
2364                             gint        *new_height)
2365 {
2366   GtkWindowGeometryInfo *info = (GtkWindowGeometryInfo *)gtk_object_get_data (GTK_OBJECT (window), "gtk-window-geometry");
2367   
2368   if (info)
2369     {
2370       GdkWindowHints flags = info->last.flags;
2371       GdkGeometry *geometry = &info->last.geometry;
2372       
2373       gtk_window_constrain_size (window,
2374                                  geometry,
2375                                  flags,
2376                                  width,
2377                                  height,
2378                                  new_width,
2379                                  new_height);
2380     }
2381 }
2382
2383
2384 /* Constrain a window size to obey the hints passed in geometry
2385  * and flags. The result will be stored in *new_width and *new_height
2386  *
2387  * This routine is partially borrowed from fvwm.
2388  *
2389  * Copyright 1993, Robert Nation
2390  *     You may use this code for any purpose, as long as the original
2391  *     copyright remains in the source code and all documentation
2392  *
2393  * which in turn borrows parts of the algorithm from uwm
2394  */
2395 static void 
2396 gtk_window_constrain_size (GtkWindow   *window,
2397                            GdkGeometry *geometry,
2398                            guint        flags,
2399                            gint         width,
2400                            gint         height,
2401                            gint        *new_width,
2402                            gint        *new_height)
2403 {
2404   gint min_width = 0;
2405   gint min_height = 0;
2406   gint base_width = 0;
2407   gint base_height = 0;
2408   gint xinc = 1;
2409   gint yinc = 1;
2410   gint max_width = G_MAXINT;
2411   gint max_height = G_MAXINT;
2412   
2413 #define FLOOR(value, base)      ( ((gint) ((value) / (base))) * (base) )
2414
2415   if ((flags & GDK_HINT_BASE_SIZE) && (flags & GDK_HINT_MIN_SIZE))
2416     {
2417       base_width = geometry->base_width;
2418       base_height = geometry->base_height;
2419       min_width = geometry->min_width;
2420       min_height = geometry->min_height;
2421     }
2422   else if (flags & GDK_HINT_BASE_SIZE)
2423     {
2424       base_width = geometry->base_width;
2425       base_height = geometry->base_height;
2426       min_width = geometry->base_width;
2427       min_height = geometry->base_height;
2428     }
2429   else if (flags & GDK_HINT_MIN_SIZE)
2430     {
2431       base_width = geometry->min_width;
2432       base_height = geometry->min_height;
2433       min_width = geometry->min_width;
2434       min_height = geometry->min_height;
2435     }
2436
2437   if (flags & GDK_HINT_MAX_SIZE)
2438     {
2439       max_width = geometry->max_width ;
2440       max_height = geometry->max_height;
2441     }
2442
2443   if (flags & GDK_HINT_RESIZE_INC)
2444     {
2445       xinc = MAX (xinc, geometry->width_inc);
2446       yinc = MAX (yinc, geometry->height_inc);
2447     }
2448   
2449   /* clamp width and height to min and max values
2450    */
2451   width = CLAMP (width, min_width, max_width);
2452   height = CLAMP (height, min_height, max_height);
2453   
2454   /* shrink to base + N * inc
2455    */
2456   width = base_width + FLOOR (width - base_width, xinc);
2457   height = base_height + FLOOR (height - base_height, yinc);
2458
2459   /* constrain aspect ratio, according to:
2460    *
2461    *                width     
2462    * min_aspect <= -------- <= max_aspect
2463    *                height    
2464    */
2465   
2466   if (flags & GDK_HINT_ASPECT &&
2467       geometry->min_aspect > 0 &&
2468       geometry->max_aspect > 0)
2469     {
2470       gint delta;
2471
2472       if (geometry->min_aspect * height > width)
2473         {
2474           delta = FLOOR (height - width * geometry->min_aspect, yinc);
2475           if (height - delta >= min_height)
2476             height -= delta;
2477           else
2478             { 
2479               delta = FLOOR (height * geometry->min_aspect - width, xinc);
2480               if (width + delta <= max_width) 
2481                 width += delta;
2482             }
2483         }
2484       
2485       if (geometry->max_aspect * height < width)
2486         {
2487           delta = FLOOR (width - height * geometry->max_aspect, xinc);
2488           if (width - delta >= min_width) 
2489             width -= delta;
2490           else
2491             {
2492               delta = FLOOR (width / geometry->max_aspect - height, yinc);
2493               if (height + delta <= max_height)
2494                 height += delta;
2495             }
2496         }
2497     }
2498
2499 #undef FLOOR
2500   
2501   *new_width = width;
2502   *new_height = height;
2503 }
2504
2505 /* Compute the set of geometry hints and flags for a window
2506  * based on the application set geometry, and requisiition
2507  * of the window. gtk_widget_size_request() must have been
2508  * called first.
2509  */
2510 static void
2511 gtk_window_compute_hints (GtkWindow   *window,
2512                           GdkGeometry *new_geometry,
2513                           guint       *new_flags)
2514 {
2515   GtkWidget *widget;
2516   GtkWidgetAuxInfo *aux_info;
2517   gint ux, uy;
2518   gint extra_width = 0;
2519   gint extra_height = 0;
2520   GtkWindowGeometryInfo *geometry_info;
2521   GtkRequisition requisition;
2522
2523   g_return_if_fail (GTK_IS_WINDOW (window));
2524
2525   widget = GTK_WIDGET (window);
2526   
2527   gtk_widget_get_child_requisition (widget, &requisition);
2528   geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
2529
2530   g_return_if_fail (geometry_info != NULL);
2531   
2532   *new_flags = geometry_info->mask;
2533   *new_geometry = geometry_info->geometry;
2534   
2535   if (geometry_info->widget)
2536     {
2537       extra_width = widget->requisition.width - geometry_info->widget->requisition.width;
2538       extra_height = widget->requisition.height - geometry_info->widget->requisition.height;
2539     }
2540   
2541   ux = 0;
2542   uy = 0;
2543   
2544   aux_info = gtk_object_get_data (GTK_OBJECT (widget), "gtk-aux-info");
2545   if (aux_info && (aux_info->x != -1) && (aux_info->y != -1))
2546     {
2547       ux = aux_info->x;
2548       uy = aux_info->y;
2549       *new_flags |= GDK_HINT_POS;
2550     }
2551   
2552   if (*new_flags & GDK_HINT_BASE_SIZE)
2553     {
2554       new_geometry->base_width += extra_width;
2555       new_geometry->base_height += extra_height;
2556     }
2557   else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
2558            (*new_flags & GDK_HINT_RESIZE_INC) &&
2559            ((extra_width != 0) || (extra_height != 0)))
2560     {
2561       *new_flags |= GDK_HINT_BASE_SIZE;
2562       
2563       new_geometry->base_width = extra_width;
2564       new_geometry->base_height = extra_height;
2565     }
2566   
2567   if (*new_flags & GDK_HINT_MIN_SIZE)
2568     {
2569       if (new_geometry->min_width < 0)
2570         new_geometry->min_width = requisition.width;
2571       else
2572         new_geometry->min_width += extra_width;
2573
2574       if (new_geometry->min_height < 0)
2575         new_geometry->min_width = requisition.height;
2576       else
2577         new_geometry->min_height += extra_height;
2578     }
2579   else if (!window->allow_shrink)
2580     {
2581       *new_flags |= GDK_HINT_MIN_SIZE;
2582       
2583       new_geometry->min_width = requisition.width;
2584       new_geometry->min_height = requisition.height;
2585     }
2586   
2587   if (*new_flags & GDK_HINT_MAX_SIZE)
2588     {
2589       if (new_geometry->max_width < 0)
2590         new_geometry->max_width = requisition.width;
2591       else
2592         new_geometry->max_width += extra_width;
2593
2594       if (new_geometry->max_height < 0)
2595         new_geometry->max_width = requisition.height;
2596       else
2597         new_geometry->max_height += extra_height;
2598     }
2599   else if (!window->allow_grow)
2600     {
2601       *new_flags |= GDK_HINT_MAX_SIZE;
2602       
2603       new_geometry->max_width = requisition.width;
2604       new_geometry->max_height = requisition.height;
2605     }
2606 }
2607
2608 /* Compute a new position for the window based on a new
2609  * size. *x and *y will be set to the new coordinates, or to -1 if the
2610  * window does not need to be moved
2611  */
2612 static void 
2613 gtk_window_compute_reposition (GtkWindow  *window,
2614                                gint        new_width,
2615                                gint        new_height,
2616                                gint       *x,
2617                                gint       *y)
2618 {
2619   GtkWidget *widget;
2620   GtkWindowPosition pos;
2621   GtkWidget *parent_widget;
2622   
2623   widget = GTK_WIDGET (window);
2624
2625   *x = -1;
2626   *y = -1;
2627
2628   parent_widget = (GtkWidget*) window->transient_parent;
2629   
2630   pos = window->position;
2631   if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
2632       (parent_widget == NULL ||
2633        !GTK_WIDGET_MAPPED (parent_widget)))
2634     pos = GTK_WIN_POS_NONE;
2635   
2636   switch (pos)
2637   {
2638     case GTK_WIN_POS_CENTER:
2639     case GTK_WIN_POS_CENTER_ALWAYS:
2640       if (window->use_uposition)
2641         {
2642           gint screen_width = gdk_screen_width ();
2643           gint screen_height = gdk_screen_height ();
2644           
2645           *x = (screen_width - new_width) / 2;
2646           *y = (screen_height - new_height) / 2;
2647         }
2648       break;
2649
2650     case GTK_WIN_POS_CENTER_ON_PARENT:
2651       if (window->use_uposition)
2652         {
2653           gint ox, oy;
2654           gdk_window_get_origin (parent_widget->window,
2655                                    &ox, &oy);
2656                                  
2657           *x = ox + (parent_widget->allocation.width - new_width) / 2;
2658           *y = oy + (parent_widget->allocation.height - new_height) / 2;
2659         }
2660       break;
2661
2662     case GTK_WIN_POS_MOUSE:
2663       if (window->use_uposition)
2664         {
2665           gint screen_width = gdk_screen_width ();
2666           gint screen_height = gdk_screen_height ();
2667           
2668           gdk_window_get_pointer (NULL, x, y, NULL);
2669           *x -= new_width / 2;
2670           *y -= new_height / 2;
2671           *x = CLAMP (*x, 0, screen_width - new_width);
2672           *y = CLAMP (*y, 0, screen_height - new_height);
2673         }
2674       break;
2675     default:
2676       if (window->use_uposition)
2677         {
2678           GtkWidgetAuxInfo *aux_info;
2679           
2680           aux_info = gtk_object_get_data (GTK_OBJECT (window), "gtk-aux-info");
2681           if (aux_info &&
2682               aux_info->x != -1 && aux_info->y != -1 &&
2683               aux_info->x != -2 && aux_info->y != -2)
2684             {
2685               *x = aux_info->x;
2686               *y = aux_info->y;
2687             }
2688         }
2689       break;
2690     }
2691
2692   if (*x != -1 && *y != -1)
2693     {
2694       GtkWidgetAuxInfo *aux_info;
2695       
2696       /* we handle necessary window positioning by hand here,
2697        * so we can coalesce the window movement with possible
2698        * resizes to get only one configure event.
2699        * keep this in sync with gtk_widget_set_uposition()
2700        * and gtk_window_reposition().
2701        */
2702       gtk_widget_set_uposition (widget, -1, -1); /* ensure we have aux_info */
2703       
2704       aux_info = gtk_object_get_data (GTK_OBJECT (widget), "gtk-aux-info");
2705       aux_info->x = *x;
2706       aux_info->y = *y;
2707
2708       window->use_uposition = FALSE;
2709     }
2710 }
2711
2712 /***********************
2713  * Redrawing functions *
2714  ***********************/
2715
2716 static void
2717 gtk_window_paint (GtkWidget     *widget,
2718                   GdkRectangle *area)
2719 {
2720   gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL, 
2721                       GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
2722 }
2723
2724 static gint
2725 gtk_window_expose (GtkWidget      *widget,
2726                    GdkEventExpose *event)
2727 {
2728   g_return_val_if_fail (widget != NULL, FALSE);
2729   g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
2730   g_return_val_if_fail (event != NULL, FALSE);
2731
2732   if (!GTK_WIDGET_APP_PAINTABLE (widget))
2733     gtk_window_paint (widget, &event->area);
2734   
2735   if (GTK_WIDGET_CLASS (parent_class)->expose_event)
2736     return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
2737
2738   return TRUE;
2739 }
2740
2741 /**
2742  * gtk_window_set_has_frame:
2743  * @window: a #GtkWindow
2744  * 
2745  * If this function is called on a window before it is realized
2746  * or showed it will have a "frame" window around widget-window,
2747  * accessible in window->frame. Using the signal frame_event
2748  * you can recieve all events targeted at the frame.
2749  * 
2750  * This function is used by the linux-fb port to implement managed
2751  * windows, but it could concievably be used by X-programs that
2752  * want to do their own window decorations.
2753  **/
2754 void
2755 gtk_window_set_has_frame (GtkWindow *window)
2756 {
2757   g_return_if_fail (window != NULL);
2758   g_return_if_fail (GTK_IS_WINDOW (window));
2759   g_return_if_fail (!GTK_WIDGET_REALIZED (window));
2760
2761   window->has_frame = TRUE;
2762 }
2763
2764 /**
2765  * gtk_window_set_frame_dimensions:
2766  * @window: a #GtkWindow that has a frame
2767  * @left: The width of the left border
2768  * @top: The height of the top border
2769  * @right: The width of the right border
2770  * @bottom: The height of the bottom border
2771  *
2772  * For windows with frames (see #gtk_window_set_has_frame) this function
2773  * can be used to change the size of the frame border.
2774  **/
2775 void
2776 gtk_window_set_frame_dimensions (GtkWindow *window, 
2777                                  gint       left,
2778                                  gint       top,
2779                                  gint       right,
2780                                  gint       bottom)
2781 {
2782   GtkWidget *widget = GTK_WIDGET (window);
2783
2784   g_return_if_fail (window != NULL);
2785   g_return_if_fail (GTK_IS_WINDOW (window));
2786
2787   if (window->frame_left == left &&
2788       window->frame_top == top &&
2789       window->frame_right == right && 
2790       window->frame_bottom == bottom)
2791     return;
2792
2793   window->frame_left = left;
2794   window->frame_top = top;
2795   window->frame_right = right;
2796   window->frame_bottom = bottom;
2797
2798   if (GTK_WIDGET_REALIZED (widget) && window->frame)
2799     {
2800       gint width = widget->allocation.width + left + right;
2801       gint height = widget->allocation.height + top + bottom;
2802       gdk_window_resize (window->frame, width, height);
2803       gtk_decorated_window_move_resize_window (window,
2804                                                left, top,
2805                                                widget->allocation.width,
2806                                                widget->allocation.height);
2807     }
2808 }
2809
2810
2811
2812 /**
2813  * gtk_window_present:
2814  * @window: a #GtkWindow
2815  *
2816  * Presents a window to the user. This may mean raising the window
2817  * in the stacking order, deiconifying it, moving it to the current
2818  * desktop, and/or giving it the keyboard focus, possibly dependent
2819  * on the user's platform, window manager, and preferences.
2820  *
2821  * If @window is hidden, this function calls gtk_widget_show()
2822  * as well.
2823  * 
2824  * This function should be used when the user tries to open a window
2825  * that's already open. Say for example the preferences dialog is
2826  * currently open, and the user chooses Preferences from the menu
2827  * a second time; use gtk_window_present() to move the already-open dialog
2828  * where the user can see it.
2829  * 
2830  **/
2831 void
2832 gtk_window_present (GtkWindow *window)
2833 {
2834   GtkWidget *widget;
2835
2836   g_return_if_fail (GTK_IS_WINDOW (window));
2837
2838   widget = GTK_WIDGET (window);
2839
2840   if (GTK_WIDGET_VISIBLE (window))
2841     {
2842       g_assert (widget->window != NULL);
2843       
2844       gdk_window_show (widget->window);
2845
2846       /* note that gdk_window_focus() will also move the window to
2847        * the current desktop, for WM spec compliant window managers.
2848        */
2849       gdk_window_focus (widget->window,
2850                         gtk_get_current_event_time ());
2851     }
2852   else
2853     {
2854       gtk_widget_show (widget);
2855     }
2856 }
2857
2858 /**
2859  * gtk_window_iconify:
2860  * @window: a #GtkWindow
2861  *
2862  * Asks to iconify @window. Note that you shouldn't assume the window
2863  * is definitely iconified afterward, because other entities (e.g. the
2864  * user or window manager) could deiconify it again, or there may not
2865  * be a window manager in which case iconification isn't possible,
2866  * etc. But normally the window will end up iconified. Just don't write
2867  * code that crashes if not.
2868  *
2869  * It's permitted to call this function before showing a window,
2870  * in which case the window will be iconified before it ever appears
2871  * onscreen.
2872  *
2873  * You can track iconification via the "window_state_event" signal
2874  * on #GtkWidget.
2875  * 
2876  **/
2877 void
2878 gtk_window_iconify (GtkWindow *window)
2879 {
2880   GtkWidget *widget;
2881   GdkWindow *toplevel;
2882   
2883   g_return_if_fail (GTK_IS_WINDOW (window));
2884
2885   widget = GTK_WIDGET (window);
2886
2887   window->iconify_initially = TRUE;
2888
2889   if (window->frame)
2890     toplevel = window->frame;
2891   else
2892     toplevel = widget->window;
2893   
2894   if (toplevel != NULL)
2895     gdk_window_iconify (toplevel);
2896 }
2897
2898 /**
2899  * gtk_window_deiconify:
2900  * @window: a #GtkWindow
2901  *
2902  * Asks to deiconify @window. Note that you shouldn't assume the
2903  * window is definitely deiconified afterward, because other entities
2904  * (e.g. the user or window manager) could iconify it again before
2905  * your code which assumes deiconification gets to run.
2906  *
2907  * You can track iconification via the "window_state_event" signal
2908  * on #GtkWidget.
2909  **/
2910 void
2911 gtk_window_deiconify (GtkWindow *window)
2912 {
2913   GtkWidget *widget;
2914   GdkWindow *toplevel;
2915   
2916   g_return_if_fail (GTK_IS_WINDOW (window));
2917
2918   widget = GTK_WIDGET (window);
2919
2920   window->iconify_initially = FALSE;
2921
2922   if (window->frame)
2923     toplevel = window->frame;
2924   else
2925     toplevel = widget->window;
2926   
2927   if (toplevel != NULL)
2928     gdk_window_deiconify (toplevel);
2929 }
2930
2931 /**
2932  * gtk_window_stick:
2933  * @window: a #GtkWindow
2934  *
2935  * Asks to stick @window, which means that it will appear on all user
2936  * desktops. Note that you shouldn't assume the window is definitely
2937  * stuck afterward, because other entities (e.g. the user or window
2938  * manager) could unstick it again, and some window managers do not
2939  * support sticking windows. But normally the window will end up
2940  * stuck. Just don't write code that crashes if not.
2941  *
2942  * It's permitted to call this function before showing a window.
2943  *
2944  * You can track stickiness via the "window_state_event" signal
2945  * on #GtkWidget.
2946  * 
2947  **/
2948 void
2949 gtk_window_stick (GtkWindow *window)
2950 {
2951   GtkWidget *widget;
2952   GdkWindow *toplevel;
2953   
2954   g_return_if_fail (GTK_IS_WINDOW (window));
2955
2956   widget = GTK_WIDGET (window);
2957
2958   window->stick_initially = TRUE;
2959
2960   if (window->frame)
2961     toplevel = window->frame;
2962   else
2963     toplevel = widget->window;
2964   
2965   if (toplevel != NULL)
2966     gdk_window_stick (toplevel);
2967 }
2968
2969 /**
2970  * gtk_window_unstick:
2971  * @window: a #GtkWindow
2972  *
2973  * Asks to unstick @window, which means that it will appear on only
2974  * one of the user's desktops. Note that you shouldn't assume the
2975  * window is definitely unstuck afterward, because other entities
2976  * (e.g. the user or window manager) could stick it again. But
2977  * normally the window will end up stuck. Just don't write code that
2978  * crashes if not.
2979  *
2980  * You can track stickiness via the "window_state_event" signal
2981  * on #GtkWidget.
2982  * 
2983  **/
2984 void
2985 gtk_window_unstick (GtkWindow *window)
2986 {
2987   GtkWidget *widget;
2988   GdkWindow *toplevel;
2989   
2990   g_return_if_fail (GTK_IS_WINDOW (window));
2991
2992   widget = GTK_WIDGET (window);
2993
2994   window->stick_initially = FALSE;
2995
2996   if (window->frame)
2997     toplevel = window->frame;
2998   else
2999     toplevel = widget->window;
3000   
3001   if (toplevel != NULL)
3002     gdk_window_unstick (toplevel);
3003 }
3004
3005 /**
3006  * gtk_window_maximize:
3007  * @window: a #GtkWindow
3008  *
3009  * Asks to maximize @window, so that it becomes full-screen. Note that
3010  * you shouldn't assume the window is definitely maximized afterward,
3011  * because other entities (e.g. the user or window manager) could
3012  * unmaximize it again, and not all window managers support
3013  * maximization. But normally the window will end up maximized. Just
3014  * don't write code that crashes if not.
3015  *
3016  * It's permitted to call this function before showing a window,
3017  * in which case the window will be maximized when it appears onscreen
3018  * initially.
3019  *
3020  * You can track maximization via the "window_state_event" signal
3021  * on #GtkWidget.
3022  * 
3023  **/
3024 void
3025 gtk_window_maximize (GtkWindow *window)
3026 {
3027   GtkWidget *widget;
3028   GdkWindow *toplevel;
3029   
3030   g_return_if_fail (GTK_IS_WINDOW (window));
3031
3032   widget = GTK_WIDGET (window);
3033
3034   window->maximize_initially = TRUE;
3035
3036   if (window->frame)
3037     toplevel = window->frame;
3038   else
3039     toplevel = widget->window;
3040   
3041   if (toplevel != NULL)
3042     gdk_window_maximize (toplevel);
3043 }
3044
3045 /**
3046  * gtk_window_unmaximize:
3047  * @window: a #GtkWindow
3048  *
3049  * Asks to unmaximize @window. Note that you shouldn't assume the
3050  * window is definitely unmaximized afterward, because other entities
3051  * (e.g. the user or window manager) could maximize it again, and not
3052  * all window managers honor requests to unmaximize. But normally the
3053  * window will end up unmaximized. Just don't write code that crashes
3054  * if not.
3055  *
3056  * You can track maximization via the "window_state_event" signal
3057  * on #GtkWidget.
3058  * 
3059  **/
3060 void
3061 gtk_window_unmaximize (GtkWindow *window)
3062 {
3063   GtkWidget *widget;
3064   GdkWindow *toplevel;
3065   
3066   g_return_if_fail (GTK_IS_WINDOW (window));
3067
3068   widget = GTK_WIDGET (window);
3069
3070   window->maximize_initially = FALSE;
3071
3072   if (window->frame)
3073     toplevel = window->frame;
3074   else
3075     toplevel = widget->window;
3076   
3077   if (toplevel != NULL)
3078     gdk_window_unmaximize (toplevel);
3079 }
3080
3081
3082
3083
3084
3085