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