]> Pileus Git - ~andy/gtk/blob - gtk/gtkwindow.c
1f90be99b305f2feae5e7030fb433ae455a69c02
[~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 #include "gtkprivate.h"
33 #include "gtkrc.h"
34 #include "gtkwindow.h"
35 #include "gtkwindow-decorate.h"
36 #include "gtkbindings.h"
37 #include "gtkkeyhash.h"
38 #include "gtkmain.h"
39 #include "gtkiconfactory.h"
40 #include "gtkintl.h"
41 #include "gtkmarshalers.h"
42 #include "gtkplug.h"
43
44 enum {
45   SET_FOCUS,
46   FRAME_EVENT,
47   ACTIVATE_FOCUS,
48   ACTIVATE_DEFAULT,
49   MOVE_FOCUS,
50   KEYS_CHANGED,
51   LAST_SIGNAL
52 };
53
54 enum {
55   PROP_0,
56
57   /* Construct */
58   PROP_TYPE,
59
60   /* Normal Props */
61   PROP_TITLE,
62   PROP_ROLE,
63   PROP_ALLOW_SHRINK,
64   PROP_ALLOW_GROW,
65   PROP_RESIZABLE,
66   PROP_MODAL,
67   PROP_WIN_POS,
68   PROP_DEFAULT_WIDTH,
69   PROP_DEFAULT_HEIGHT,
70   PROP_DESTROY_WITH_PARENT,
71   PROP_ICON,
72   PROP_SCREEN,
73   PROP_TYPE_HINT,
74   PROP_SKIP_TASKBAR_HINT,
75   PROP_SKIP_PAGER_HINT,
76   PROP_DECORATED,
77   PROP_GRAVITY,
78   
79   /* Readonly properties */
80   PROP_IS_ACTIVE,
81   PROP_HAS_TOPLEVEL_FOCUS,
82   
83   LAST_ARG
84 };
85
86 typedef struct
87 {
88   GList     *icon_list;
89   GdkPixmap *icon_pixmap;
90   GdkPixmap *icon_mask;
91   guint      realized : 1;
92   guint      using_default_icon : 1;
93   guint      using_parent_icon : 1;
94 } GtkWindowIconInfo;
95
96 typedef struct {
97   GdkGeometry    geometry; /* Last set of geometry hints we set */
98   GdkWindowHints flags;
99   GdkRectangle   configure_request;
100 } GtkWindowLastGeometryInfo;
101
102 struct _GtkWindowGeometryInfo
103 {
104   /* Properties that the app has set on the window
105    */
106   GdkGeometry    geometry;      /* Geometry hints */
107   GdkWindowHints mask;
108   GtkWidget     *widget;        /* subwidget to which hints apply */
109   /* from last gtk_window_resize () - if > 0, indicates that
110    * we should resize to this size.
111    */
112   gint           resize_width;  
113   gint           resize_height;
114
115   /* From last gtk_window_move () prior to mapping -
116    * only used if initial_pos_set
117    */
118   gint           initial_x;
119   gint           initial_y;
120   
121   /* Default size - used only the FIRST time we map a window,
122    * only if > 0.
123    */
124   gint           default_width; 
125   gint           default_height;
126   /* whether to use initial_x, initial_y */
127   guint          initial_pos_set : 1;
128   /* CENTER_ALWAYS or other position constraint changed since
129    * we sent the last configure request.
130    */
131   guint          position_constraints_changed : 1;
132
133   /* if true, default_width, height come from gtk_window_parse_geometry,
134    * and thus should be multiplied by the increments and affect the
135    * geometry widget only
136    */
137   guint          default_is_geometry : 1;
138   
139   GtkWindowLastGeometryInfo last;
140 };
141
142 typedef struct _GtkWindowMnemonic GtkWindowMnemonic;
143
144 struct _GtkWindowMnemonic {
145   GtkWindow *window;
146   guint keyval;
147
148   GSList *targets;
149 };
150
151 #define GTK_WINDOW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_WINDOW, GtkWindowPrivate))
152
153 typedef struct _GtkWindowPrivate GtkWindowPrivate;
154
155 struct _GtkWindowPrivate
156 {
157   guint above_initially : 1;
158   guint below_initially : 1;
159   guint fullscreen_initially : 1;
160   guint skips_taskbar : 1;
161   guint skips_pager : 1;
162 };
163
164 static void gtk_window_class_init         (GtkWindowClass    *klass);
165 static void gtk_window_init               (GtkWindow         *window);
166 static void gtk_window_dispose            (GObject           *object);
167 static void gtk_window_destroy            (GtkObject         *object);
168 static void gtk_window_finalize           (GObject           *object);
169 static void gtk_window_show               (GtkWidget         *widget);
170 static void gtk_window_hide               (GtkWidget         *widget);
171 static void gtk_window_map                (GtkWidget         *widget);
172 static void gtk_window_unmap              (GtkWidget         *widget);
173 static void gtk_window_realize            (GtkWidget         *widget);
174 static void gtk_window_unrealize          (GtkWidget         *widget);
175 static void gtk_window_size_request       (GtkWidget         *widget,
176                                            GtkRequisition    *requisition);
177 static void gtk_window_size_allocate      (GtkWidget         *widget,
178                                            GtkAllocation     *allocation);
179 static gint gtk_window_event              (GtkWidget *widget,
180                                            GdkEvent *event);
181 static gboolean gtk_window_frame_event    (GtkWindow *window,
182                                            GdkEvent *event);
183 static gint gtk_window_configure_event    (GtkWidget         *widget,
184                                            GdkEventConfigure *event);
185 static gint gtk_window_key_press_event    (GtkWidget         *widget,
186                                            GdkEventKey       *event);
187 static gint gtk_window_key_release_event  (GtkWidget         *widget,
188                                            GdkEventKey       *event);
189 static gint gtk_window_enter_notify_event (GtkWidget         *widget,
190                                            GdkEventCrossing  *event);
191 static gint gtk_window_leave_notify_event (GtkWidget         *widget,
192                                            GdkEventCrossing  *event);
193 static gint gtk_window_focus_in_event     (GtkWidget         *widget,
194                                            GdkEventFocus     *event);
195 static gint gtk_window_focus_out_event    (GtkWidget         *widget,
196                                            GdkEventFocus     *event);
197 static gint gtk_window_client_event       (GtkWidget         *widget,
198                                            GdkEventClient    *event);
199 static void gtk_window_check_resize       (GtkContainer      *container);
200 static gint gtk_window_focus              (GtkWidget        *widget,
201                                            GtkDirectionType  direction);
202 static void gtk_window_real_set_focus     (GtkWindow         *window,
203                                            GtkWidget         *focus);
204
205 static void gtk_window_real_activate_default (GtkWindow         *window);
206 static void gtk_window_real_activate_focus   (GtkWindow         *window);
207 static void gtk_window_move_focus            (GtkWindow         *window,
208                                               GtkDirectionType   dir);
209 static void gtk_window_keys_changed          (GtkWindow         *window);
210 static void gtk_window_read_rcfiles       (GtkWidget         *widget,
211                                            GdkEventClient    *event);
212 static void gtk_window_paint              (GtkWidget         *widget,
213                                            GdkRectangle      *area);
214 static gint gtk_window_expose             (GtkWidget         *widget,
215                                            GdkEventExpose    *event);
216 static void gtk_window_unset_transient_for         (GtkWindow  *window);
217 static void gtk_window_transient_parent_realized   (GtkWidget  *parent,
218                                                     GtkWidget  *window);
219 static void gtk_window_transient_parent_unrealized (GtkWidget  *parent,
220                                                     GtkWidget  *window);
221
222 static GdkScreen *gtk_window_check_screen (GtkWindow *window);
223
224 static GtkWindowGeometryInfo* gtk_window_get_geometry_info         (GtkWindow    *window,
225                                                                     gboolean      create);
226
227 static void     gtk_window_move_resize               (GtkWindow    *window);
228 static gboolean gtk_window_compare_hints             (GdkGeometry  *geometry_a,
229                                                       guint         flags_a,
230                                                       GdkGeometry  *geometry_b,
231                                                       guint         flags_b);
232 static void     gtk_window_constrain_size            (GtkWindow    *window,
233                                                       GdkGeometry  *geometry,
234                                                       guint         flags,
235                                                       gint          width,
236                                                       gint          height,
237                                                       gint         *new_width,
238                                                       gint         *new_height);
239 static void     gtk_window_constrain_position        (GtkWindow    *window,
240                                                       gint          new_width,
241                                                       gint          new_height,
242                                                       gint         *x,
243                                                       gint         *y);
244 static void     gtk_window_compute_hints             (GtkWindow    *window,
245                                                       GdkGeometry  *new_geometry,
246                                                       guint        *new_flags);
247 static void     gtk_window_compute_configure_request (GtkWindow    *window,
248                                                       GdkRectangle *request,
249                                                       GdkGeometry  *geometry,
250                                                       guint        *flags);
251
252 static void     gtk_window_set_default_size_internal (GtkWindow    *window,
253                                                       gboolean      change_width,
254                                                       gint          width,
255                                                       gboolean      change_height,
256                                                       gint          height,
257                                                       gboolean      is_geometry);
258
259 static void     gtk_window_realize_icon               (GtkWindow    *window);
260 static void     gtk_window_unrealize_icon             (GtkWindow    *window);
261
262 static void        gtk_window_notify_keys_changed (GtkWindow   *window);
263 static GtkKeyHash *gtk_window_get_key_hash        (GtkWindow   *window);
264 static void        gtk_window_free_key_hash       (GtkWindow   *window);
265
266 static GSList      *toplevel_list = NULL;
267 static GHashTable  *mnemonic_hash_table = NULL;
268 static GtkBinClass *parent_class = NULL;
269 static guint        window_signals[LAST_SIGNAL] = { 0 };
270 static GList       *default_icon_list = NULL;
271 static guint        default_icon_serial = 0;
272 static gboolean     disable_startup_notification = FALSE;
273 static gboolean     sent_startup_notification = FALSE;
274
275 static void gtk_window_set_property (GObject         *object,
276                                      guint            prop_id,
277                                      const GValue    *value,
278                                      GParamSpec      *pspec);
279 static void gtk_window_get_property (GObject         *object,
280                                      guint            prop_id,
281                                      GValue          *value,
282                                      GParamSpec      *pspec);
283
284
285 static guint
286 mnemonic_hash (gconstpointer key)
287 {
288   const GtkWindowMnemonic *k;
289   guint h;
290   
291   k = (GtkWindowMnemonic *)key;
292   
293   h = (gulong) k->window;
294   h ^= k->keyval << 16;
295   h ^= k->keyval >> 16;
296
297   return h;
298 }
299
300 static gboolean
301 mnemonic_equal (gconstpointer a, gconstpointer b)
302 {
303   const GtkWindowMnemonic *ka;
304   const GtkWindowMnemonic *kb;
305   
306   ka = (GtkWindowMnemonic *)a;
307   kb = (GtkWindowMnemonic *)b;
308
309   return
310     (ka->window == kb->window) &&
311     (ka->keyval == kb->keyval);
312 }
313
314 GType
315 gtk_window_get_type (void)
316 {
317   static GType window_type = 0;
318
319   if (!window_type)
320     {
321       static const GTypeInfo window_info =
322       {
323         sizeof (GtkWindowClass),
324         NULL,           /* base_init */
325         NULL,           /* base_finalize */
326         (GClassInitFunc) gtk_window_class_init,
327         NULL,           /* class_finalize */
328         NULL,           /* class_data */
329         sizeof (GtkWindow),
330         0,              /* n_preallocs */
331         (GInstanceInitFunc) gtk_window_init,
332       };
333
334       window_type = g_type_register_static (GTK_TYPE_BIN, "GtkWindow",
335                                             &window_info, 0);
336     }
337
338   return window_type;
339 }
340
341 static void
342 add_tab_bindings (GtkBindingSet    *binding_set,
343                   GdkModifierType   modifiers,
344                   GtkDirectionType  direction)
345 {
346   gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
347                                 "move_focus", 1,
348                                 GTK_TYPE_DIRECTION_TYPE, direction);
349   gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
350                                 "move_focus", 1,
351                                 GTK_TYPE_DIRECTION_TYPE, direction);
352 }
353
354 static void
355 add_arrow_bindings (GtkBindingSet    *binding_set,
356                     guint             keysym,
357                     GtkDirectionType  direction)
358 {
359   guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
360   
361   gtk_binding_entry_add_signal (binding_set, keysym, 0,
362                                 "move_focus", 1,
363                                 GTK_TYPE_DIRECTION_TYPE, direction);
364   gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
365                                 "move_focus", 1,
366                                 GTK_TYPE_DIRECTION_TYPE, direction);
367   gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
368                                 "move_focus", 1,
369                                 GTK_TYPE_DIRECTION_TYPE, direction);
370   gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
371                                 "move_focus", 1,
372                                 GTK_TYPE_DIRECTION_TYPE, direction);
373 }
374
375
376 static void
377 gtk_window_class_init (GtkWindowClass *klass)
378 {
379   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
380   GtkObjectClass *object_class;
381   GtkWidgetClass *widget_class;
382   GtkContainerClass *container_class;
383   GtkBindingSet *binding_set;
384   
385   object_class = (GtkObjectClass*) klass;
386   widget_class = (GtkWidgetClass*) klass;
387   container_class = (GtkContainerClass*) klass;
388   
389   parent_class = g_type_class_peek_parent (klass);
390
391   mnemonic_hash_table = g_hash_table_new (mnemonic_hash, mnemonic_equal);
392
393   gobject_class->dispose = gtk_window_dispose;
394   gobject_class->finalize = gtk_window_finalize;
395
396   gobject_class->set_property = gtk_window_set_property;
397   gobject_class->get_property = gtk_window_get_property;
398   
399   object_class->destroy = gtk_window_destroy;
400
401   widget_class->show = gtk_window_show;
402   widget_class->hide = gtk_window_hide;
403   widget_class->map = gtk_window_map;
404   widget_class->unmap = gtk_window_unmap;
405   widget_class->realize = gtk_window_realize;
406   widget_class->unrealize = gtk_window_unrealize;
407   widget_class->size_request = gtk_window_size_request;
408   widget_class->size_allocate = gtk_window_size_allocate;
409   widget_class->configure_event = gtk_window_configure_event;
410   widget_class->key_press_event = gtk_window_key_press_event;
411   widget_class->key_release_event = gtk_window_key_release_event;
412   widget_class->enter_notify_event = gtk_window_enter_notify_event;
413   widget_class->leave_notify_event = gtk_window_leave_notify_event;
414   widget_class->focus_in_event = gtk_window_focus_in_event;
415   widget_class->focus_out_event = gtk_window_focus_out_event;
416   widget_class->client_event = gtk_window_client_event;
417   widget_class->focus = gtk_window_focus;
418   
419   widget_class->expose_event = gtk_window_expose;
420    
421   container_class->check_resize = gtk_window_check_resize;
422
423   klass->set_focus = gtk_window_real_set_focus;
424   klass->frame_event = gtk_window_frame_event;
425
426   klass->activate_default = gtk_window_real_activate_default;
427   klass->activate_focus = gtk_window_real_activate_focus;
428   klass->move_focus = gtk_window_move_focus;
429   klass->keys_changed = gtk_window_keys_changed;
430   
431   g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate));
432   
433   /* Construct */
434   g_object_class_install_property (gobject_class,
435                                    PROP_TYPE,
436                                    g_param_spec_enum ("type",
437                                                       _("Window Type"),
438                                                       _("The type of the window"),
439                                                       GTK_TYPE_WINDOW_TYPE,
440                                                       GTK_WINDOW_TOPLEVEL,
441                                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
442   /* Regular Props */
443   g_object_class_install_property (gobject_class,
444                                    PROP_TITLE,
445                                    g_param_spec_string ("title",
446                                                         _("Window Title"),
447                                                         _("The title of the window"),
448                                                         NULL,
449                                                         G_PARAM_READWRITE));
450
451   g_object_class_install_property (gobject_class,
452                                    PROP_ROLE,
453                                    g_param_spec_string ("role",
454                                                         _("Window Role"),
455                                                         _("Unique identifier for the window to be used when restoring a session"),
456                                                         NULL,
457                                                         G_PARAM_READWRITE));
458
459   g_object_class_install_property (gobject_class,
460                                    PROP_ALLOW_SHRINK,
461                                    g_param_spec_boolean ("allow_shrink",
462                                                          _("Allow Shrink"),
463                                                          /* xgettext:no-c-format */
464                                                          _("If TRUE, the window has no mimimum size. Setting this to TRUE is 99% of the time a bad idea"),
465                                                          FALSE,
466                                                          G_PARAM_READWRITE));
467
468   g_object_class_install_property (gobject_class,
469                                    PROP_ALLOW_GROW,
470                                    g_param_spec_boolean ("allow_grow",
471                                                          _("Allow Grow"),
472                                                          _("If TRUE, users can expand the window beyond its minimum size"),
473                                                          TRUE,
474                                                          G_PARAM_READWRITE));
475
476   g_object_class_install_property (gobject_class,
477                                    PROP_RESIZABLE,
478                                    g_param_spec_boolean ("resizable",
479                                                          _("Resizable"),
480                                                          _("If TRUE, users can resize the window"),
481                                                          TRUE,
482                                                          G_PARAM_READWRITE));
483   
484   g_object_class_install_property (gobject_class,
485                                    PROP_MODAL,
486                                    g_param_spec_boolean ("modal",
487                                                          _("Modal"),
488                                                          _("If TRUE, the window is modal (other windows are not usable while this one is up)"),
489                                                          FALSE,
490                                                          G_PARAM_READWRITE));
491
492   g_object_class_install_property (gobject_class,
493                                    PROP_WIN_POS,
494                                    g_param_spec_enum ("window_position",
495                                                       _("Window Position"),
496                                                       _("The initial position of the window"),
497                                                       GTK_TYPE_WINDOW_POSITION,
498                                                       GTK_WIN_POS_NONE,
499                                                       G_PARAM_READWRITE));
500  
501   g_object_class_install_property (gobject_class,
502                                    PROP_DEFAULT_WIDTH,
503                                    g_param_spec_int ("default_width",
504                                                      _("Default Width"),
505                                                      _("The default width of the window, used when initially showing the window"),
506                                                      -1,
507                                                      G_MAXINT,
508                                                      -1,
509                                                      G_PARAM_READWRITE));
510   
511   g_object_class_install_property (gobject_class,
512                                    PROP_DEFAULT_HEIGHT,
513                                    g_param_spec_int ("default_height",
514                                                      _("Default Height"),
515                                                      _("The default height of the window, used when initially showing the window"),
516                                                      -1,
517                                                      G_MAXINT,
518                                                      -1,
519                                                      G_PARAM_READWRITE));
520   
521   g_object_class_install_property (gobject_class,
522                                    PROP_DESTROY_WITH_PARENT,
523                                    g_param_spec_boolean ("destroy_with_parent",
524                                                          _("Destroy with Parent"),
525                                                          _("If this window should be destroyed when the parent is destroyed"),
526                                                          FALSE,
527                                                          G_PARAM_READWRITE));
528
529   g_object_class_install_property (gobject_class,
530                                    PROP_ICON,
531                                    g_param_spec_object ("icon",
532                                                         _("Icon"),
533                                                         _("Icon for this window"),
534                                                         GDK_TYPE_PIXBUF,
535                                                         G_PARAM_READWRITE));
536   
537   g_object_class_install_property (gobject_class,
538                                    PROP_SCREEN,
539                                    g_param_spec_object ("screen",
540                                                         _("Screen"),
541                                                         _("The screen where this window will be displayed"),
542                                                         GDK_TYPE_SCREEN,
543                                                         G_PARAM_READWRITE));
544
545   g_object_class_install_property (gobject_class,
546                                    PROP_IS_ACTIVE,
547                                    g_param_spec_boolean ("is_active",
548                                                          _("Is Active"),
549                                                          _("Whether the toplevel is the current active window"),
550                                                          FALSE,
551                                                          G_PARAM_READABLE));
552   
553   g_object_class_install_property (gobject_class,
554                                    PROP_HAS_TOPLEVEL_FOCUS,
555                                    g_param_spec_boolean ("has_toplevel_focus",
556                                                          _("Focus in Toplevel"),
557                                                          _("Whether the input focus is within this GtkWindow"),
558                                                          FALSE,
559                                                          G_PARAM_READABLE));
560
561   g_object_class_install_property (gobject_class,
562                                    PROP_TYPE_HINT,
563                                    g_param_spec_enum ("type_hint",
564                                                       _("Type hint"),
565                                                       _("Hint to help the desktop environment understand what kind of window this is and how to treat it."),
566                                                       GDK_TYPE_WINDOW_TYPE_HINT,
567                                                       GDK_WINDOW_TYPE_HINT_NORMAL,
568                                                       G_PARAM_READWRITE));
569
570   g_object_class_install_property (gobject_class,
571                                    PROP_SKIP_TASKBAR_HINT,
572                                    g_param_spec_boolean ("skip_taskbar_hint",
573                                                          _("Skip taskbar"),
574                                                          _("TRUE if the window should not be in the task bar."),
575                                                          FALSE,
576                                                          G_PARAM_READWRITE));
577
578   g_object_class_install_property (gobject_class,
579                                    PROP_SKIP_PAGER_HINT,
580                                    g_param_spec_boolean ("skip_pager_hint",
581                                                          _("Skip pager"),
582                                                          _("TRUE if the window should not be in the pager."),
583                                                          FALSE,
584                                                          G_PARAM_READWRITE));  
585
586   /**
587    * GtkWindow:decorated:
588    *
589    * Whether the window should be decorated by the window manager.
590    *
591    * Since: 2.4
592    */
593   g_object_class_install_property (gobject_class,
594                                    PROP_DECORATED,
595                                    g_param_spec_boolean ("decorated",
596                                                          _("Decorated"),
597                                                          _("Whether the window should be decorated by the window manager"),
598                                                          TRUE,
599                                                          G_PARAM_READWRITE));
600
601   /**
602    * GtkWindow:gravity:
603    *
604    * The window gravity of the window. See gtk_window_move() and #GdkGravity for
605    * more details about window gravity.
606    *
607    * Since: 2.4
608    */
609   g_object_class_install_property (gobject_class,
610                                    PROP_GRAVITY,
611                                    g_param_spec_enum ("gravity",
612                                                       _("Gravity"),
613                                                       _("The window gravity of the window"),
614                                                       GDK_TYPE_GRAVITY,
615                                                       GDK_GRAVITY_NORTH_WEST,
616                                                       G_PARAM_READWRITE));
617
618   window_signals[SET_FOCUS] =
619     g_signal_new ("set_focus",
620                   G_TYPE_FROM_CLASS (gobject_class),
621                   G_SIGNAL_RUN_LAST,
622                   G_STRUCT_OFFSET (GtkWindowClass, set_focus),
623                   NULL, NULL,
624                   _gtk_marshal_VOID__OBJECT,
625                   G_TYPE_NONE, 1,
626                   GTK_TYPE_WIDGET);
627   
628   window_signals[FRAME_EVENT] =
629     g_signal_new ("frame_event",
630                   G_TYPE_FROM_CLASS (gobject_class),
631                   G_SIGNAL_RUN_LAST,
632                   G_STRUCT_OFFSET(GtkWindowClass, frame_event),
633                   _gtk_boolean_handled_accumulator, NULL,
634                   _gtk_marshal_BOOLEAN__BOXED,
635                   G_TYPE_BOOLEAN, 1,
636                   GDK_TYPE_EVENT);
637
638   window_signals[ACTIVATE_FOCUS] =
639     g_signal_new ("activate_focus",
640                   G_TYPE_FROM_CLASS (gobject_class),
641                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
642                   G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
643                   NULL, NULL,
644                   _gtk_marshal_VOID__VOID,
645                   G_TYPE_NONE,
646                   0);
647
648   window_signals[ACTIVATE_DEFAULT] =
649     g_signal_new ("activate_default",
650                   G_TYPE_FROM_CLASS (gobject_class),
651                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
652                   G_STRUCT_OFFSET (GtkWindowClass, activate_default),
653                   NULL, NULL,
654                   _gtk_marshal_VOID__VOID,
655                   G_TYPE_NONE,
656                   0);
657
658   window_signals[MOVE_FOCUS] =
659     g_signal_new ("move_focus",
660                   G_TYPE_FROM_CLASS (gobject_class),
661                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
662                   G_STRUCT_OFFSET (GtkWindowClass, move_focus),
663                   NULL, NULL,
664                   _gtk_marshal_VOID__ENUM,
665                   G_TYPE_NONE,
666                   1,
667                   GTK_TYPE_DIRECTION_TYPE);
668
669   window_signals[KEYS_CHANGED] =
670     g_signal_new ("keys_changed",
671                   G_TYPE_FROM_CLASS (gobject_class),
672                   G_SIGNAL_RUN_FIRST,
673                   G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
674                   NULL, NULL,
675                   _gtk_marshal_VOID__VOID,
676                   G_TYPE_NONE,
677                   0);
678
679   /*
680    * Key bindings
681    */
682
683   binding_set = gtk_binding_set_by_class (klass);
684
685   gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
686                                 "activate_focus", 0);
687   gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0,
688                                 "activate_focus", 0);
689   
690   gtk_binding_entry_add_signal (binding_set, GDK_Return, 0,
691                                 "activate_default", 0);
692
693   gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
694                                 "activate_default", 0);
695
696   add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
697   add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
698   add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
699   add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
700
701   add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
702   add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
703   add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
704   add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
705 }
706
707 static void
708 gtk_window_init (GtkWindow *window)
709 {
710   GdkColormap *colormap;
711   
712   GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
713   GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
714
715   GTK_PRIVATE_SET_FLAG (window, GTK_ANCHORED);
716
717   gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
718
719   window->title = NULL;
720   window->wmclass_name = g_strdup (g_get_prgname ());
721   window->wmclass_class = g_strdup (gdk_get_program_class ());
722   window->wm_role = NULL;
723   window->geometry_info = NULL;
724   window->type = GTK_WINDOW_TOPLEVEL;
725   window->focus_widget = NULL;
726   window->default_widget = NULL;
727   window->configure_request_count = 0;
728   window->allow_shrink = FALSE;
729   window->allow_grow = TRUE;
730   window->configure_notify_received = FALSE;
731   window->position = GTK_WIN_POS_NONE;
732   window->need_default_size = TRUE;
733   window->need_default_position = TRUE;
734   window->modal = FALSE;
735   window->frame = NULL;
736   window->has_frame = FALSE;
737   window->frame_left = 0;
738   window->frame_right = 0;
739   window->frame_top = 0;
740   window->frame_bottom = 0;
741   window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
742   window->gravity = GDK_GRAVITY_NORTH_WEST;
743   window->decorated = TRUE;
744   window->mnemonic_modifier = GDK_MOD1_MASK;
745   window->screen = gdk_screen_get_default ();
746   
747   colormap = _gtk_widget_peek_colormap ();
748   if (colormap)
749     gtk_widget_set_colormap (GTK_WIDGET (window), colormap);
750   
751   g_object_ref (window);
752   gtk_object_sink (GTK_OBJECT (window));
753   window->has_user_ref_count = TRUE;
754   toplevel_list = g_slist_prepend (toplevel_list, window);
755
756   gtk_decorated_window_init (window);
757
758   g_signal_connect (window,
759                     "event",
760                     G_CALLBACK (gtk_window_event),
761                     NULL);
762 }
763
764 static void
765 gtk_window_set_property (GObject      *object,
766                          guint         prop_id,
767                          const GValue *value,
768                          GParamSpec   *pspec)
769 {
770   GtkWindow  *window;
771   
772   window = GTK_WINDOW (object);
773
774   switch (prop_id)
775     {
776     case PROP_TYPE:
777       window->type = g_value_get_enum (value);
778       break;
779     case PROP_TITLE:
780       gtk_window_set_title (window, g_value_get_string (value));
781       break;
782     case PROP_ROLE:
783       gtk_window_set_role (window, g_value_get_string (value));
784       break;
785     case PROP_ALLOW_SHRINK:
786       window->allow_shrink = g_value_get_boolean (value);
787       gtk_widget_queue_resize (GTK_WIDGET (window));
788       break;
789     case PROP_ALLOW_GROW:
790       window->allow_grow = g_value_get_boolean (value);
791       gtk_widget_queue_resize (GTK_WIDGET (window));
792       g_object_notify (G_OBJECT (window), "resizable");
793       break;
794     case PROP_RESIZABLE:
795       window->allow_grow = g_value_get_boolean (value);
796       gtk_widget_queue_resize (GTK_WIDGET (window));
797       g_object_notify (G_OBJECT (window), "allow_grow");
798       break;
799     case PROP_MODAL:
800       gtk_window_set_modal (window, g_value_get_boolean (value));
801       break;
802     case PROP_WIN_POS:
803       gtk_window_set_position (window, g_value_get_enum (value));
804       break;
805     case PROP_DEFAULT_WIDTH:
806       gtk_window_set_default_size_internal (window,
807                                             TRUE, g_value_get_int (value),
808                                             FALSE, -1, FALSE);
809       break;
810     case PROP_DEFAULT_HEIGHT:
811       gtk_window_set_default_size_internal (window,
812                                             FALSE, -1,
813                                             TRUE, g_value_get_int (value), FALSE);
814       break;
815     case PROP_DESTROY_WITH_PARENT:
816       gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
817       break;
818     case PROP_ICON:
819       gtk_window_set_icon (window,
820                            g_value_get_object (value));
821       break;
822     case PROP_SCREEN:
823       gtk_window_set_screen (window, g_value_get_object (value));
824       break;
825     case PROP_TYPE_HINT:
826       gtk_window_set_type_hint (window,
827                                 g_value_get_enum (value));
828       break;
829     case PROP_SKIP_TASKBAR_HINT:
830       gtk_window_set_skip_taskbar_hint (window,
831                                         g_value_get_boolean (value));
832       break;
833     case PROP_SKIP_PAGER_HINT:
834       gtk_window_set_skip_pager_hint (window,
835                                       g_value_get_boolean (value));
836       break;
837     case PROP_DECORATED:
838       gtk_window_set_decorated (window, g_value_get_boolean (value));
839       break;
840     case PROP_GRAVITY:
841       gtk_window_set_gravity (window, g_value_get_enum (value));
842       break;
843     default:
844       break;
845     }
846 }
847
848 static void
849 gtk_window_get_property (GObject      *object,
850                          guint         prop_id,
851                          GValue       *value,
852                          GParamSpec   *pspec)
853 {
854   GtkWindow  *window;
855
856   window = GTK_WINDOW (object);
857
858   switch (prop_id)
859     {
860       GtkWindowGeometryInfo *info;
861     case PROP_TYPE:
862       g_value_set_enum (value, window->type);
863       break;
864     case PROP_ROLE:
865       g_value_set_string (value, window->wm_role);
866       break;
867     case PROP_TITLE:
868       g_value_set_string (value, window->title);
869       break;
870     case PROP_ALLOW_SHRINK:
871       g_value_set_boolean (value, window->allow_shrink);
872       break;
873     case PROP_ALLOW_GROW:
874       g_value_set_boolean (value, window->allow_grow);
875       break;
876     case PROP_RESIZABLE:
877       g_value_set_boolean (value, window->allow_grow);
878       break;
879     case PROP_MODAL:
880       g_value_set_boolean (value, window->modal);
881       break;
882     case PROP_WIN_POS:
883       g_value_set_enum (value, window->position);
884       break;
885     case PROP_DEFAULT_WIDTH:
886       info = gtk_window_get_geometry_info (window, FALSE);
887       if (!info)
888         g_value_set_int (value, -1);
889       else
890         g_value_set_int (value, info->default_width);
891       break;
892     case PROP_DEFAULT_HEIGHT:
893       info = gtk_window_get_geometry_info (window, FALSE);
894       if (!info)
895         g_value_set_int (value, -1);
896       else
897         g_value_set_int (value, info->default_height);
898       break;
899     case PROP_DESTROY_WITH_PARENT:
900       g_value_set_boolean (value, window->destroy_with_parent);
901       break;
902     case PROP_ICON:
903       g_value_set_object (value, gtk_window_get_icon (window));
904       break;
905     case PROP_SCREEN:
906       g_value_set_object (value, window->screen);
907       break;
908     case PROP_IS_ACTIVE:
909       g_value_set_boolean (value, window->is_active);
910       break;
911     case PROP_HAS_TOPLEVEL_FOCUS:
912       g_value_set_boolean (value, window->has_toplevel_focus);
913       break;
914     case PROP_TYPE_HINT:
915       g_value_set_enum (value,
916                         window->type_hint);
917       break;
918     case PROP_SKIP_TASKBAR_HINT:
919       g_value_set_boolean (value,
920                            gtk_window_get_skip_taskbar_hint (window));
921       break;
922     case PROP_SKIP_PAGER_HINT:
923       g_value_set_boolean (value,
924                            gtk_window_get_skip_pager_hint (window));
925       break;
926     case PROP_DECORATED:
927       g_value_set_boolean (value, gtk_window_get_decorated (window));
928       break;
929     case PROP_GRAVITY:
930       g_value_set_enum (value, gtk_window_get_gravity (window));
931       break;
932     default:
933       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
934       break;
935     }
936 }
937
938 /**
939  * gtk_window_new:
940  * @type: type of window
941  * 
942  * Creates a new #GtkWindow, which is a toplevel window that can
943  * contain other widgets. Nearly always, the type of the window should
944  * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
945  * popup menu from scratch (which is a bad idea, just use #GtkMenu),
946  * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
947  * dialogs, though in some other toolkits dialogs are called "popups".
948  * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
949  * On X11, popup windows are not controlled by the <link
950  * linkend="gtk-X11-arch">window manager</link>.
951  *
952  * If you simply want an undecorated window (no window borders), use
953  * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
954  * 
955  * Return value: a new #GtkWindow.
956  **/
957 GtkWidget*
958 gtk_window_new (GtkWindowType type)
959 {
960   GtkWindow *window;
961
962   g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
963
964   window = g_object_new (GTK_TYPE_WINDOW, NULL);
965
966   window->type = type;
967
968   return GTK_WIDGET (window);
969 }
970
971 /**
972  * gtk_window_set_title:
973  * @window: a #GtkWindow
974  * @title: title of the window
975  * 
976  * Sets the title of the #GtkWindow. The title of a window will be
977  * displayed in its title bar; on the X Window System, the title bar
978  * is rendered by the <link linkend="gtk-X11-arch">window
979  * manager</link>, so exactly how the title appears to users may vary
980  * according to a user's exact configuration. The title should help a
981  * user distinguish this window from other windows they may have
982  * open. A good title might include the application name and current
983  * document filename, for example.
984  * 
985  **/
986 void
987 gtk_window_set_title (GtkWindow   *window,
988                       const gchar *title)
989 {
990   char *new_title;
991   
992   g_return_if_fail (GTK_IS_WINDOW (window));
993
994   new_title = g_strdup (title);
995   g_free (window->title);
996   window->title = new_title;
997
998   if (GTK_WIDGET_REALIZED (window))
999     {
1000       gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
1001
1002       gtk_decorated_window_set_title (window, title);
1003     }
1004
1005   g_object_notify (G_OBJECT (window), "title");
1006 }
1007
1008 /**
1009  * gtk_window_get_title:
1010  * @window: a #GtkWindow
1011  *
1012  * Retrieves the title of the window. See gtk_window_set_title().
1013  *
1014  * Return value: the title of the window, or %NULL if none has
1015  *    been set explicitely. The returned string is owned by the widget
1016  *    and must not be modified or freed.
1017  **/
1018 G_CONST_RETURN gchar *
1019 gtk_window_get_title (GtkWindow *window)
1020 {
1021   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1022
1023   return window->title;
1024 }
1025
1026 /**
1027  * gtk_window_set_wmclass:
1028  * @window: a #GtkWindow
1029  * @wmclass_name: window name hint
1030  * @wmclass_class: window class hint
1031  *
1032  * Don't use this function. It sets the X Window System "class" and
1033  * "name" hints for a window.  According to the ICCCM, you should
1034  * always set these to the same value for all windows in an
1035  * application, and GTK+ sets them to that value by default, so calling
1036  * this function is sort of pointless. However, you may want to call
1037  * gtk_window_set_role() on each window in your application, for the
1038  * benefit of the session manager. Setting the role allows the window
1039  * manager to restore window positions when loading a saved session.
1040  * 
1041  **/
1042 void
1043 gtk_window_set_wmclass (GtkWindow *window,
1044                         const gchar *wmclass_name,
1045                         const gchar *wmclass_class)
1046 {
1047   g_return_if_fail (GTK_IS_WINDOW (window));
1048
1049   g_free (window->wmclass_name);
1050   window->wmclass_name = g_strdup (wmclass_name);
1051
1052   g_free (window->wmclass_class);
1053   window->wmclass_class = g_strdup (wmclass_class);
1054
1055   if (GTK_WIDGET_REALIZED (window))
1056     g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
1057 }
1058
1059 /**
1060  * gtk_window_set_role:
1061  * @window: a #GtkWindow
1062  * @role: unique identifier for the window to be used when restoring a session
1063  *
1064  * This function is only useful on X11, not with other GTK+ targets.
1065  * 
1066  * In combination with the window title, the window role allows a
1067  * <link linkend="gtk-X11-arch">window manager</link> to identify "the
1068  * same" window when an application is restarted. So for example you
1069  * might set the "toolbox" role on your app's toolbox window, so that
1070  * when the user restarts their session, the window manager can put
1071  * the toolbox back in the same place.
1072  *
1073  * If a window already has a unique title, you don't need to set the
1074  * role, since the WM can use the title to identify the window when
1075  * restoring the session.
1076  * 
1077  **/
1078 void
1079 gtk_window_set_role (GtkWindow   *window,
1080                      const gchar *role)
1081 {
1082   char *new_role;
1083   
1084   g_return_if_fail (GTK_IS_WINDOW (window));
1085
1086   new_role = g_strdup (role);
1087   g_free (window->wm_role);
1088   window->wm_role = new_role;
1089
1090   if (GTK_WIDGET_REALIZED (window))
1091     gdk_window_set_role (GTK_WIDGET (window)->window, window->wm_role);
1092
1093   g_object_notify (G_OBJECT (window), "role");
1094 }
1095
1096 /**
1097  * gtk_window_get_role:
1098  * @window: a #GtkWindow
1099  *
1100  * Returns the role of the window. See gtk_window_set_role() for
1101  * further explanation.
1102  *
1103  * Return value: the role of the window if set, or %NULL. The
1104  *   returned is owned by the widget and must not be modified
1105  *   or freed.
1106  **/
1107 G_CONST_RETURN gchar *
1108 gtk_window_get_role (GtkWindow *window)
1109 {
1110   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1111
1112   return window->wm_role;
1113 }
1114
1115 /**
1116  * gtk_window_set_focus:
1117  * @window: a #GtkWindow
1118  * @focus: widget to be the new focus widget, or %NULL to unset
1119  *   any focus widget for the toplevel window.
1120  *
1121  * If @focus is not the current focus widget, and is focusable, sets
1122  * it as the focus widget for the window. If @focus is %NULL, unsets
1123  * the focus widget for this window. To set the focus to a particular
1124  * widget in the toplevel, it is usually more convenient to use
1125  * gtk_widget_grab_focus() instead of this function.
1126  **/
1127 void
1128 gtk_window_set_focus (GtkWindow *window,
1129                       GtkWidget *focus)
1130 {
1131   g_return_if_fail (GTK_IS_WINDOW (window));
1132   if (focus)
1133     {
1134       g_return_if_fail (GTK_IS_WIDGET (focus));
1135       g_return_if_fail (GTK_WIDGET_CAN_FOCUS (focus));
1136     }
1137
1138   if (focus)
1139     gtk_widget_grab_focus (focus);
1140   else
1141     {
1142       /* Clear the existing focus chain, so that when we focus into
1143        * the window again, we start at the beginnning.
1144        */
1145       GtkWidget *widget = window->focus_widget;
1146       if (widget)
1147         {
1148           while (widget->parent)
1149             {
1150               widget = widget->parent;
1151               gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
1152             }
1153         }
1154       
1155       _gtk_window_internal_set_focus (window, NULL);
1156     }
1157 }
1158
1159 void
1160 _gtk_window_internal_set_focus (GtkWindow *window,
1161                                 GtkWidget *focus)
1162 {
1163   g_return_if_fail (GTK_IS_WINDOW (window));
1164
1165   if ((window->focus_widget != focus) ||
1166       (focus && !GTK_WIDGET_HAS_FOCUS (focus)))
1167     g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
1168 }
1169
1170 /**
1171  * gtk_window_set_default:
1172  * @window: a #GtkWindow
1173  * @default_widget: widget to be the default, or %NULL to unset the
1174  *                  default widget for the toplevel.
1175  *
1176  * The default widget is the widget that's activated when the user
1177  * presses Enter in a dialog (for example). This function sets or
1178  * unsets the default widget for a #GtkWindow about. When setting
1179  * (rather than unsetting) the default widget it's generally easier to
1180  * call gtk_widget_grab_focus() on the widget. Before making a widget
1181  * the default widget, you must set the #GTK_CAN_DEFAULT flag on the
1182  * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS().
1183  **/
1184 void
1185 gtk_window_set_default (GtkWindow *window,
1186                         GtkWidget *default_widget)
1187 {
1188   g_return_if_fail (GTK_IS_WINDOW (window));
1189
1190   if (default_widget)
1191     g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
1192   
1193   if (window->default_widget != default_widget)
1194     {
1195       GtkWidget *old_default_widget = NULL;
1196       
1197       if (default_widget)
1198         g_object_ref (default_widget);
1199       
1200       if (window->default_widget)
1201         {
1202           old_default_widget = window->default_widget;
1203           
1204           if (window->focus_widget != window->default_widget ||
1205               !GTK_WIDGET_RECEIVES_DEFAULT (window->default_widget))
1206             GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1207           gtk_widget_queue_draw (window->default_widget);
1208         }
1209
1210       window->default_widget = default_widget;
1211
1212       if (window->default_widget)
1213         {
1214           if (window->focus_widget == NULL ||
1215               !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))
1216             GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
1217           gtk_widget_queue_draw (window->default_widget);
1218         }
1219
1220       if (old_default_widget)
1221         g_object_notify (G_OBJECT (old_default_widget), "has_default");
1222       
1223       if (default_widget)
1224         {
1225           g_object_notify (G_OBJECT (default_widget), "has_default");
1226           g_object_unref (default_widget);
1227         }
1228     }
1229 }
1230
1231 void
1232 gtk_window_set_policy (GtkWindow *window,
1233                        gboolean   allow_shrink,
1234                        gboolean   allow_grow,
1235                        gboolean   auto_shrink)
1236 {
1237   g_return_if_fail (GTK_IS_WINDOW (window));
1238
1239   window->allow_shrink = (allow_shrink != FALSE);
1240   window->allow_grow = (allow_grow != FALSE);
1241
1242   g_object_freeze_notify (G_OBJECT (window));
1243   g_object_notify (G_OBJECT (window), "allow_shrink");
1244   g_object_notify (G_OBJECT (window), "allow_grow");
1245   g_object_notify (G_OBJECT (window), "resizable");
1246   g_object_thaw_notify (G_OBJECT (window));
1247   
1248   gtk_widget_queue_resize (GTK_WIDGET (window));
1249 }
1250
1251 static gboolean
1252 handle_keys_changed (gpointer data)
1253 {
1254   GtkWindow *window;
1255
1256   GDK_THREADS_ENTER ();
1257   window = GTK_WINDOW (data);
1258
1259   if (window->keys_changed_handler)
1260     {
1261       g_source_remove (window->keys_changed_handler);
1262       window->keys_changed_handler = 0;
1263     }
1264
1265   g_signal_emit (window, window_signals[KEYS_CHANGED], 0);
1266   GDK_THREADS_LEAVE ();
1267   
1268   return FALSE;
1269 }
1270
1271 static void
1272 gtk_window_notify_keys_changed (GtkWindow *window)
1273 {
1274   if (!window->keys_changed_handler)
1275     window->keys_changed_handler = g_idle_add (handle_keys_changed, window);
1276 }
1277
1278 /**
1279  * gtk_window_add_accel_group:
1280  * @window: window to attach accelerator group to
1281  * @accel_group: a #GtkAccelGroup
1282  *
1283  * Associate @accel_group with @window, such that calling
1284  * gtk_accel_groups_activate() on @window will activate accelerators
1285  * in @accel_group.
1286  **/
1287 void
1288 gtk_window_add_accel_group (GtkWindow     *window,
1289                             GtkAccelGroup *accel_group)
1290 {
1291   g_return_if_fail (GTK_IS_WINDOW (window));
1292   g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1293
1294   _gtk_accel_group_attach (accel_group, G_OBJECT (window));
1295   g_signal_connect_object (accel_group, "accel_changed",
1296                            G_CALLBACK (gtk_window_notify_keys_changed),
1297                            window, G_CONNECT_SWAPPED);
1298 }
1299
1300 /**
1301  * gtk_window_remove_accel_group:
1302  * @window: a #GtkWindow
1303  * @accel_group: a #GtkAccelGroup
1304  *
1305  * Reverses the effects of gtk_window_add_accel_group().
1306  **/
1307 void
1308 gtk_window_remove_accel_group (GtkWindow     *window,
1309                                GtkAccelGroup *accel_group)
1310 {
1311   g_return_if_fail (GTK_IS_WINDOW (window));
1312   g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
1313
1314   g_signal_handlers_disconnect_by_func (accel_group,
1315                                         gtk_window_notify_keys_changed,
1316                                         window);
1317   _gtk_accel_group_detach (accel_group, G_OBJECT (window));
1318 }
1319
1320 /**
1321  * gtk_window_add_mnemonic:
1322  * @window: a #GtkWindow
1323  * @keyval: the mnemonic
1324  * @target: the widget that gets activated by the mnemonic
1325  *
1326  * Adds a mnemonic to this window.
1327  */
1328 void
1329 gtk_window_add_mnemonic (GtkWindow *window,
1330                          guint      keyval,
1331                          GtkWidget *target)
1332 {
1333   GtkWindowMnemonic key;
1334   GtkWindowMnemonic *mnemonic;
1335
1336   g_return_if_fail (GTK_IS_WINDOW (window));
1337   g_return_if_fail (GTK_IS_WIDGET (target));
1338   
1339   key.window = window;
1340   key.keyval = keyval;
1341   mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1342
1343   if (mnemonic)
1344     {
1345       g_return_if_fail (g_slist_find (mnemonic->targets, target) == NULL);
1346       mnemonic->targets = g_slist_append (mnemonic->targets, target);
1347     }
1348   else
1349     {
1350       mnemonic = g_new (GtkWindowMnemonic, 1);
1351       *mnemonic = key;
1352       mnemonic->targets = g_slist_prepend (NULL, target);
1353       g_hash_table_insert (mnemonic_hash_table, mnemonic, mnemonic);
1354     }
1355   gtk_window_notify_keys_changed (window);
1356 }
1357
1358 /**
1359  * gtk_window_remove_mnemonic:
1360  * @window: a #GtkWindow
1361  * @keyval: the mnemonic
1362  * @target: the widget that gets activated by the mnemonic
1363  *
1364  * Removes a mnemonic from this window.
1365  */
1366 void
1367 gtk_window_remove_mnemonic (GtkWindow *window,
1368                             guint      keyval,
1369                             GtkWidget *target)
1370 {
1371   GtkWindowMnemonic key;
1372   GtkWindowMnemonic *mnemonic;
1373
1374   g_return_if_fail (GTK_IS_WINDOW (window));
1375   g_return_if_fail (GTK_IS_WIDGET (target));
1376   
1377   key.window = window;
1378   key.keyval = keyval;
1379   mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1380
1381   g_return_if_fail (mnemonic && g_slist_find (mnemonic->targets, target) != NULL);
1382
1383   mnemonic->targets = g_slist_remove (mnemonic->targets, target);
1384   if (mnemonic->targets == NULL)
1385     {
1386       g_hash_table_remove (mnemonic_hash_table, mnemonic);
1387       g_free (mnemonic);
1388     }
1389   gtk_window_notify_keys_changed (window);
1390 }
1391
1392 /**
1393  * gtk_window_mnemonic_activate:
1394  * @window: a #GtkWindow
1395  * @keyval: the mnemonic
1396  * @modifier: the modifiers 
1397  * @returns: %TRUE if the activation is done. 
1398  * 
1399  * Activates the targets associated with the mnemonic.
1400  */
1401 gboolean
1402 gtk_window_mnemonic_activate (GtkWindow      *window,
1403                               guint           keyval,
1404                               GdkModifierType modifier)
1405 {
1406   GtkWindowMnemonic key;
1407   GtkWindowMnemonic *mnemonic;
1408   GSList *list;
1409   GtkWidget *widget, *chosen_widget;
1410   gboolean overloaded;
1411
1412   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1413
1414   if (window->mnemonic_modifier != (modifier & gtk_accelerator_get_default_mod_mask ()))
1415     return FALSE;
1416   
1417   key.window = window;
1418   key.keyval = keyval;
1419   mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
1420
1421   if (!mnemonic)
1422     return FALSE;
1423   
1424   overloaded = FALSE;
1425   chosen_widget = NULL;
1426   list = mnemonic->targets;
1427   while (list)
1428     {
1429       widget = GTK_WIDGET (list->data);
1430       
1431       if (GTK_WIDGET_IS_SENSITIVE (widget) &&
1432           GTK_WIDGET_MAPPED (widget))
1433         {
1434           if (chosen_widget)
1435             {
1436               overloaded = TRUE;
1437               break;
1438             }
1439           else
1440             chosen_widget = widget;
1441         }
1442       list = g_slist_next (list);
1443     }
1444
1445   if (chosen_widget)
1446     {
1447       /* For round robin we put the activated entry on
1448        * the end of the list after activation
1449        */
1450       mnemonic->targets = g_slist_remove (mnemonic->targets, chosen_widget);
1451       mnemonic->targets = g_slist_append (mnemonic->targets, chosen_widget);
1452
1453       return gtk_widget_mnemonic_activate (chosen_widget, overloaded);
1454     }
1455   return FALSE;
1456 }
1457
1458 /**
1459  * gtk_window_set_mnemonic_modifier:
1460  * @window: a #GtkWindow
1461  * @modifier: the modifier mask used to activate
1462  *               mnemonics on this window.
1463  *
1464  * Sets the mnemonic modifier for this window. 
1465  **/
1466 void
1467 gtk_window_set_mnemonic_modifier (GtkWindow      *window,
1468                                   GdkModifierType modifier)
1469 {
1470   g_return_if_fail (GTK_IS_WINDOW (window));
1471   g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
1472
1473   window->mnemonic_modifier = modifier;
1474   gtk_window_notify_keys_changed (window);
1475 }
1476
1477 /**
1478  * gtk_window_get_mnemonic_modifier:
1479  * @window: a #GtkWindow
1480  *
1481  * Returns the mnemonic modifier for this window. See
1482  * gtk_window_set_mnemonic_modifier().
1483  *
1484  * Return value: the modifier mask used to activate
1485  *               mnemonics on this window.
1486  **/
1487 GdkModifierType
1488 gtk_window_get_mnemonic_modifier (GtkWindow *window)
1489 {
1490   g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
1491
1492   return window->mnemonic_modifier;
1493 }
1494
1495 /**
1496  * gtk_window_set_position:
1497  * @window: a #GtkWindow.
1498  * @position: a position constraint.
1499  *
1500  * Sets a position constraint for this window. If the old or new
1501  * constraint is %GTK_WIN_POS_CENTER_ALWAYS, this will also cause
1502  * the window to be repositioned to satisfy the new constraint. 
1503  **/
1504 void
1505 gtk_window_set_position (GtkWindow         *window,
1506                          GtkWindowPosition  position)
1507 {
1508   g_return_if_fail (GTK_IS_WINDOW (window));
1509
1510   if (position == GTK_WIN_POS_CENTER_ALWAYS ||
1511       window->position == GTK_WIN_POS_CENTER_ALWAYS)
1512     {
1513       GtkWindowGeometryInfo *info;
1514
1515       info = gtk_window_get_geometry_info (window, TRUE);
1516
1517       /* this flag causes us to re-request the CENTER_ALWAYS
1518        * constraint in gtk_window_move_resize(), see
1519        * comment in that function.
1520        */
1521       info->position_constraints_changed = TRUE;
1522
1523       gtk_widget_queue_resize (GTK_WIDGET (window));
1524     }
1525
1526   window->position = position;
1527   
1528   g_object_notify (G_OBJECT (window), "window_position");
1529 }
1530
1531 /**
1532  * gtk_window_activate_focus:
1533  * @window: a #GtkWindow
1534  * 
1535  * Activates the current focused widget within the window.
1536  * 
1537  * Return value: %TRUE if a widget got activated.
1538  **/
1539 gboolean 
1540 gtk_window_activate_focus (GtkWindow *window)
1541 {
1542   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1543
1544   if (window->focus_widget)
1545     {
1546       if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1547         gtk_widget_activate (window->focus_widget);
1548       return TRUE;
1549     }
1550
1551   return FALSE;
1552 }
1553
1554 /**
1555  * gtk_window_get_focus:
1556  * @window: a #GtkWindow
1557  * 
1558  * Retrieves the current focused widget within the window.
1559  * Note that this is the widget that would have the focus
1560  * if the toplevel window focused; if the toplevel window
1561  * is not focused then  <literal>GTK_WIDGET_HAS_FOCUS (widget)</literal> will
1562  * not be %TRUE for the widget. 
1563  * 
1564  * Return value: the currently focused widget, or %NULL if there is none.
1565  **/
1566 GtkWidget *
1567 gtk_window_get_focus (GtkWindow *window)
1568 {
1569   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1570
1571   return window->focus_widget;
1572 }
1573
1574 /**
1575  * gtk_window_activate_default:
1576  * @window: a #GtkWindow
1577  * 
1578  * Activates the default widget for the window, unless the current 
1579  * focused widget has been configured to receive the default action 
1580  * (see #GTK_RECEIVES_DEFAULT in #GtkWidgetFlags), in which case the
1581  * focused widget is activated. 
1582  * 
1583  * Return value: %TRUE if a widget got activated.
1584  **/
1585 gboolean
1586 gtk_window_activate_default (GtkWindow *window)
1587 {
1588   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1589
1590   if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
1591       (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
1592     {
1593       gtk_widget_activate (window->default_widget);
1594       return TRUE;
1595     }
1596   else if (window->focus_widget)
1597     {
1598       if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
1599         gtk_widget_activate (window->focus_widget);
1600       return TRUE;
1601     }
1602
1603   return FALSE;
1604 }
1605
1606 /**
1607  * gtk_window_set_modal:
1608  * @window: a #GtkWindow
1609  * @modal: whether the window is modal
1610  * 
1611  * Sets a window modal or non-modal. Modal windows prevent interaction
1612  * with other windows in the same application. To keep modal dialogs
1613  * on top of main application windows, use
1614  * gtk_window_set_transient_for() to make the dialog transient for the
1615  * parent; most <link linkend="gtk-X11-arch">window managers</link>
1616  * will then disallow lowering the dialog below the parent.
1617  * 
1618  * 
1619  **/
1620 void
1621 gtk_window_set_modal (GtkWindow *window,
1622                       gboolean   modal)
1623 {
1624   g_return_if_fail (GTK_IS_WINDOW (window));
1625
1626   modal = modal != FALSE;
1627   if (window->modal == modal)
1628     return;
1629   
1630   window->modal = modal;
1631   
1632   /* adjust desired modality state */
1633   if (GTK_WIDGET_REALIZED (window))
1634     {
1635       GtkWidget *widget = GTK_WIDGET (window);
1636       
1637       if (window->modal)
1638         gdk_window_set_modal_hint (widget->window, TRUE);
1639       else
1640         gdk_window_set_modal_hint (widget->window, FALSE);
1641     }
1642
1643   if (GTK_WIDGET_VISIBLE (window))
1644     {
1645       if (window->modal)
1646         gtk_grab_add (GTK_WIDGET (window));
1647       else
1648         gtk_grab_remove (GTK_WIDGET (window));
1649     }
1650
1651   g_object_notify (G_OBJECT (window), "modal");
1652 }
1653
1654 /**
1655  * gtk_window_get_modal:
1656  * @window: a #GtkWindow
1657  * 
1658  * Returns whether the window is modal. See gtk_window_set_modal().
1659  *
1660  * Return value: %TRUE if the window is set to be modal and
1661  *               establishes a grab when shown
1662  **/
1663 gboolean
1664 gtk_window_get_modal (GtkWindow *window)
1665 {
1666   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
1667
1668   return window->modal;
1669 }
1670
1671 /**
1672  * gtk_window_list_toplevels:
1673  * 
1674  * Returns a list of all existing toplevel windows. The widgets
1675  * in the list are not individually referenced. If you want
1676  * to iterate through the list and perform actions involving
1677  * callbacks that might destroy the widgets, you <emphasis>must</emphasis> call
1678  * <literal>g_list_foreach (result, (GFunc)g_object_ref, NULL)</literal> first, and
1679  * then unref all the widgets afterwards.
1680  * 
1681  * Return value: list of toplevel widgets
1682  **/
1683 GList*
1684 gtk_window_list_toplevels (void)
1685 {
1686   GList *list = NULL;
1687   GSList *slist;
1688
1689   for (slist = toplevel_list; slist; slist = slist->next)
1690     list = g_list_prepend (list, slist->data);
1691
1692   return list;
1693 }
1694
1695 void
1696 gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
1697 {
1698   GList *embedded_windows;
1699
1700   g_return_if_fail (GTK_IS_WINDOW (window));
1701
1702   embedded_windows = g_object_get_data (G_OBJECT (window), "gtk-embedded");
1703   if (embedded_windows)
1704     g_object_steal_qdata (G_OBJECT (window), 
1705                           g_quark_from_static_string ("gtk-embedded"));
1706   embedded_windows = g_list_prepend (embedded_windows,
1707                                      GUINT_TO_POINTER (xid));
1708
1709   g_object_set_data_full (G_OBJECT (window), "gtk-embedded", 
1710                           embedded_windows,
1711                           embedded_windows ?
1712                             (GDestroyNotify) g_list_free : NULL);
1713 }
1714
1715 void
1716 gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
1717 {
1718   GList *embedded_windows;
1719   GList *node;
1720
1721   g_return_if_fail (GTK_IS_WINDOW (window));
1722   
1723   embedded_windows = g_object_get_data (G_OBJECT (window), "gtk-embedded");
1724   if (embedded_windows)
1725     g_object_steal_qdata (G_OBJECT (window), 
1726                           g_quark_from_static_string ("gtk-embedded"));
1727
1728   node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
1729   if (node)
1730     {
1731       embedded_windows = g_list_remove_link (embedded_windows, node);
1732       g_list_free_1 (node);
1733     }
1734   
1735   g_object_set_data_full (G_OBJECT (window), "gtk-embedded",
1736                           embedded_windows,
1737                           embedded_windows ?
1738                             (GDestroyNotify) g_list_free : NULL);
1739 }
1740
1741 void       
1742 _gtk_window_reposition (GtkWindow *window,
1743                         gint       x,
1744                         gint       y)
1745 {
1746   g_return_if_fail (GTK_IS_WINDOW (window));
1747
1748   gtk_window_move (window, x, y);
1749 }
1750
1751 static void
1752 gtk_window_dispose (GObject *object)
1753 {
1754   GtkWindow *window = GTK_WINDOW (object);
1755
1756   gtk_window_set_focus (window, NULL);
1757   gtk_window_set_default (window, NULL);
1758
1759   G_OBJECT_CLASS (parent_class)->dispose (object);
1760 }
1761
1762 static void
1763 parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
1764 {
1765   gtk_widget_destroy (GTK_WIDGET (child));
1766 }
1767
1768 static void
1769 connect_parent_destroyed (GtkWindow *window)
1770 {
1771   if (window->transient_parent)
1772     {
1773       g_signal_connect (window->transient_parent,
1774                         "destroy",
1775                         G_CALLBACK (parent_destroyed_callback),
1776                         window);
1777     }  
1778 }
1779
1780 static void
1781 disconnect_parent_destroyed (GtkWindow *window)
1782 {
1783   if (window->transient_parent)
1784     {
1785       g_signal_handlers_disconnect_by_func (window->transient_parent,
1786                                             parent_destroyed_callback,
1787                                             window);
1788     }
1789 }
1790
1791 static void
1792 gtk_window_transient_parent_realized (GtkWidget *parent,
1793                                       GtkWidget *window)
1794 {
1795   if (GTK_WIDGET_REALIZED (window))
1796     gdk_window_set_transient_for (window->window, parent->window);
1797 }
1798
1799 static void
1800 gtk_window_transient_parent_unrealized (GtkWidget *parent,
1801                                         GtkWidget *window)
1802 {
1803   if (GTK_WIDGET_REALIZED (window))
1804     gdk_property_delete (window->window, 
1805                          gdk_atom_intern ("WM_TRANSIENT_FOR", FALSE));
1806 }
1807
1808 static void
1809 gtk_window_transient_parent_screen_changed (GtkWindow   *parent,
1810                                             GParamSpec  *pspec,
1811                                             GtkWindow   *window)
1812 {
1813   gtk_window_set_screen (window, parent->screen);
1814 }
1815
1816 static void       
1817 gtk_window_unset_transient_for  (GtkWindow *window)
1818 {
1819   if (window->transient_parent)
1820     {
1821       g_signal_handlers_disconnect_by_func (window->transient_parent,
1822                                             gtk_window_transient_parent_realized,
1823                                             window);
1824       g_signal_handlers_disconnect_by_func (window->transient_parent,
1825                                             gtk_window_transient_parent_unrealized,
1826                                             window);
1827       g_signal_handlers_disconnect_by_func (window->transient_parent,
1828                                             gtk_window_transient_parent_screen_changed,
1829                                             window);
1830       g_signal_handlers_disconnect_by_func (window->transient_parent,
1831                                             gtk_widget_destroyed,
1832                                             &window->transient_parent);
1833
1834       if (window->destroy_with_parent)
1835         disconnect_parent_destroyed (window);
1836       
1837       window->transient_parent = NULL;
1838     }
1839 }
1840
1841 /**
1842  * gtk_window_set_transient_for:
1843  * @window: a #GtkWindow
1844  * @parent: parent window
1845  *
1846  * Dialog windows should be set transient for the main application
1847  * window they were spawned from. This allows <link
1848  * linkend="gtk-X11-arch">window managers</link> to e.g. keep the
1849  * dialog on top of the main window, or center the dialog over the
1850  * main window. gtk_dialog_new_with_buttons() and other convenience
1851  * functions in GTK+ will sometimes call
1852  * gtk_window_set_transient_for() on your behalf.
1853  *
1854  * On Windows, this function will and put the child window
1855  * on top of the parent, much as the window manager would have
1856  * done on X.
1857  * 
1858  **/
1859 void       
1860 gtk_window_set_transient_for  (GtkWindow *window, 
1861                                GtkWindow *parent)
1862 {
1863   g_return_if_fail (GTK_IS_WINDOW (window));
1864   g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
1865   g_return_if_fail (window != parent);
1866
1867     
1868   if (window->transient_parent)
1869     {
1870       if (GTK_WIDGET_REALIZED (window) && 
1871           GTK_WIDGET_REALIZED (window->transient_parent) && 
1872           (!parent || !GTK_WIDGET_REALIZED (parent)))
1873         gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
1874                                                 GTK_WIDGET (window));
1875
1876       gtk_window_unset_transient_for (window);
1877     }
1878
1879   window->transient_parent = parent;
1880
1881   if (parent)
1882     {
1883       g_signal_connect (parent, "destroy",
1884                         G_CALLBACK (gtk_widget_destroyed),
1885                         &window->transient_parent);
1886       g_signal_connect (parent, "realize",
1887                         G_CALLBACK (gtk_window_transient_parent_realized),
1888                         window);
1889       g_signal_connect (parent, "unrealize",
1890                         G_CALLBACK (gtk_window_transient_parent_unrealized),
1891                         window);
1892       g_signal_connect (parent, "notify::screen",
1893                         G_CALLBACK (gtk_window_transient_parent_screen_changed),
1894                         window);
1895       
1896       gtk_window_set_screen (window, parent->screen);
1897
1898       if (window->destroy_with_parent)
1899         connect_parent_destroyed (window);
1900       
1901       if (GTK_WIDGET_REALIZED (window) &&
1902           GTK_WIDGET_REALIZED (parent))
1903         gtk_window_transient_parent_realized (GTK_WIDGET (parent),
1904                                               GTK_WIDGET (window));
1905     }
1906 }
1907
1908 /**
1909  * gtk_window_get_transient_for:
1910  * @window: a #GtkWindow
1911  *
1912  * Fetches the transient parent for this window. See
1913  * gtk_window_set_transient_for().
1914  *
1915  * Return value: the transient parent for this window, or %NULL
1916  *    if no transient parent has been set.
1917  **/
1918 GtkWindow *
1919 gtk_window_get_transient_for (GtkWindow *window)
1920 {
1921   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
1922
1923   return window->transient_parent;
1924 }
1925
1926 /**
1927  * gtk_window_set_type_hint:
1928  * @window: a #GtkWindow
1929  * @hint: the window type
1930  *
1931  * By setting the type hint for the window, you allow the window
1932  * manager to decorate and handle the window in a way which is
1933  * suitable to the function of the window in your application.
1934  *
1935  * This function should be called before the window becomes visible.
1936  *
1937  * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
1938  * will sometimes call gtk_window_set_type_hint() on your behalf.
1939  * 
1940  **/
1941 void
1942 gtk_window_set_type_hint (GtkWindow           *window, 
1943                           GdkWindowTypeHint    hint)
1944 {
1945   g_return_if_fail (GTK_IS_WINDOW (window));
1946   g_return_if_fail (!GTK_WIDGET_VISIBLE (window));
1947   window->type_hint = hint;
1948 }
1949
1950 /**
1951  * gtk_window_get_type_hint:
1952  * @window: a #GtkWindow
1953  *
1954  * Gets the type hint for this window. See gtk_window_set_type_hint().
1955  *
1956  * Return value: the type hint for @window.
1957  **/
1958 GdkWindowTypeHint
1959 gtk_window_get_type_hint (GtkWindow *window)
1960 {
1961   g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
1962
1963   return window->type_hint;
1964 }
1965
1966 /**
1967  * gtk_window_set_skip_taskbar_hint:
1968  * @window: a #GtkWindow 
1969  * @setting: %TRUE to keep this window from appearing in the task bar
1970  * 
1971  * Windows may set a hint asking the desktop environment not to display
1972  * the window in the task bar. This function toggles this hint.
1973  * 
1974  * Since: 2.2
1975  **/
1976 void
1977 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
1978                                   gboolean   setting)
1979 {
1980   GtkWindowPrivate *priv;
1981
1982   g_return_if_fail (GTK_IS_WINDOW (window));
1983   
1984   priv = GTK_WINDOW_GET_PRIVATE (window);
1985
1986   setting = setting != FALSE;
1987
1988   if (priv->skips_taskbar != setting)
1989     {
1990       priv->skips_taskbar = setting;
1991       if (GTK_WIDGET_REALIZED (window))
1992         gdk_window_set_skip_taskbar_hint (GTK_WIDGET (window)->window,
1993                                           priv->skips_taskbar);
1994       g_object_notify (G_OBJECT (window), "skip_taskbar_hint");
1995     }
1996 }
1997
1998 /**
1999  * gtk_window_get_skip_taskbar_hint:
2000  * @window: a #GtkWindow
2001  * 
2002  * Gets the value set by gtk_window_set_skip_taskbar_hint()
2003  * 
2004  * Return value: %TRUE if window shouldn't be in taskbar
2005  * 
2006  * Since: 2.2
2007  **/
2008 gboolean
2009 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2010 {
2011   GtkWindowPrivate *priv;
2012
2013   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2014   
2015   priv = GTK_WINDOW_GET_PRIVATE (window);
2016
2017   return priv->skips_taskbar;
2018 }
2019
2020 /**
2021  * gtk_window_set_skip_pager_hint:
2022  * @window: a #GtkWindow 
2023  * @setting: %TRUE to keep this window from appearing in the pager
2024  * 
2025  * Windows may set a hint asking the desktop environment not to display
2026  * the window in the pager. This function toggles this hint.
2027  * (A "pager" is any desktop navigation tool such as a workspace
2028  * switcher that displays a thumbnail representation of the windows
2029  * on the screen.)
2030  * 
2031  * Since: 2.2
2032  **/
2033 void
2034 gtk_window_set_skip_pager_hint (GtkWindow *window,
2035                                 gboolean   setting)
2036 {
2037   GtkWindowPrivate *priv;
2038
2039   g_return_if_fail (GTK_IS_WINDOW (window));
2040   
2041   priv = GTK_WINDOW_GET_PRIVATE (window);
2042
2043   setting = setting != FALSE;
2044
2045   if (priv->skips_pager != setting)
2046     {
2047       priv->skips_pager = setting;
2048       if (GTK_WIDGET_REALIZED (window))
2049         gdk_window_set_skip_pager_hint (GTK_WIDGET (window)->window,
2050                                         priv->skips_pager);
2051       g_object_notify (G_OBJECT (window), "skip_pager_hint");
2052     }
2053 }
2054
2055 /**
2056  * gtk_window_get_skip_pager_hint:
2057  * @window: a #GtkWindow
2058  * 
2059  * Gets the value set by gtk_window_set_skip_pager_hint().
2060  * 
2061  * Return value: %TRUE if window shouldn't be in pager
2062  * 
2063  * Since: 2.2
2064  **/
2065 gboolean
2066 gtk_window_get_skip_pager_hint (GtkWindow *window)
2067 {
2068   GtkWindowPrivate *priv;
2069
2070   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2071   
2072   priv = GTK_WINDOW_GET_PRIVATE (window);
2073
2074   return priv->skips_pager;
2075 }
2076
2077 /**
2078  * gtk_window_set_destroy_with_parent:
2079  * @window: a #GtkWindow
2080  * @setting: whether to destroy @window with its transient parent
2081  * 
2082  * If @setting is %TRUE, then destroying the transient parent of @window
2083  * will also destroy @window itself. This is useful for dialogs that
2084  * shouldn't persist beyond the lifetime of the main window they're
2085  * associated with, for example.
2086  **/
2087 void
2088 gtk_window_set_destroy_with_parent  (GtkWindow *window,
2089                                      gboolean   setting)
2090 {
2091   g_return_if_fail (GTK_IS_WINDOW (window));
2092
2093   if (window->destroy_with_parent == (setting != FALSE))
2094     return;
2095
2096   if (window->destroy_with_parent)
2097     {
2098       disconnect_parent_destroyed (window);
2099     }
2100   else
2101     {
2102       connect_parent_destroyed (window);
2103     }
2104   
2105   window->destroy_with_parent = setting;
2106
2107   g_object_notify (G_OBJECT (window), "destroy_with_parent");
2108 }
2109
2110 /**
2111  * gtk_window_get_destroy_with_parent:
2112  * @window: a #GtkWindow
2113  * 
2114  * Returns whether the window will be destroyed with its transient parent. See
2115  * gtk_window_set_destroy_with_parent ().
2116  *
2117  * Return value: %TRUE if the window will be destroyed with its transient parent.
2118  **/
2119 gboolean
2120 gtk_window_get_destroy_with_parent (GtkWindow *window)
2121 {
2122   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2123
2124   return window->destroy_with_parent;
2125 }
2126
2127 static GtkWindowGeometryInfo*
2128 gtk_window_get_geometry_info (GtkWindow *window,
2129                               gboolean   create)
2130 {
2131   GtkWindowGeometryInfo *info;
2132
2133   info = window->geometry_info;
2134   if (!info && create)
2135     {
2136       info = g_new0 (GtkWindowGeometryInfo, 1);
2137
2138       info->default_width = -1;
2139       info->default_height = -1;
2140       info->resize_width = -1;
2141       info->resize_height = -1;
2142       info->initial_x = 0;
2143       info->initial_y = 0;
2144       info->initial_pos_set = FALSE;
2145       info->default_is_geometry = FALSE;
2146       info->position_constraints_changed = FALSE;
2147       info->last.configure_request.x = 0;
2148       info->last.configure_request.y = 0;
2149       info->last.configure_request.width = -1;
2150       info->last.configure_request.height = -1;
2151       info->widget = NULL;
2152       info->mask = 0;
2153       window->geometry_info = info;
2154     }
2155
2156   return info;
2157 }
2158
2159 /**
2160  * gtk_window_set_geometry_hints:
2161  * @window: a #GtkWindow
2162  * @geometry_widget: widget the geometry hints will be applied to
2163  * @geometry: struct containing geometry information
2164  * @geom_mask: mask indicating which struct fields should be paid attention to
2165  *
2166  * This function sets up hints about how a window can be resized by
2167  * the user.  You can set a minimum and maximum size; allowed resize
2168  * increments (e.g. for xterm, you can only resize by the size of a
2169  * character); aspect ratios; and more. See the #GdkGeometry struct.
2170  * 
2171  **/
2172 void       
2173 gtk_window_set_geometry_hints (GtkWindow       *window,
2174                                GtkWidget       *geometry_widget,
2175                                GdkGeometry     *geometry,
2176                                GdkWindowHints   geom_mask)
2177 {
2178   GtkWindowGeometryInfo *info;
2179
2180   g_return_if_fail (GTK_IS_WINDOW (window));
2181   g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
2182
2183   info = gtk_window_get_geometry_info (window, TRUE);
2184   
2185   if (info->widget)
2186     g_signal_handlers_disconnect_by_func (info->widget,
2187                                           gtk_widget_destroyed,
2188                                           &info->widget);
2189   
2190   info->widget = geometry_widget;
2191   if (info->widget)
2192     g_signal_connect (geometry_widget, "destroy",
2193                       G_CALLBACK (gtk_widget_destroyed),
2194                       &info->widget);
2195
2196   if (geometry)
2197     info->geometry = *geometry;
2198
2199   /* We store gravity in window->gravity not in the hints. */
2200   info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
2201
2202   if (geom_mask & GDK_HINT_WIN_GRAVITY)
2203     {
2204       gtk_window_set_gravity (window, geometry->win_gravity);
2205     }
2206   
2207   gtk_widget_queue_resize (GTK_WIDGET (window));
2208 }
2209
2210 /**
2211  * gtk_window_set_decorated:
2212  * @window: a #GtkWindow
2213  * @setting: %TRUE to decorate the window
2214  *
2215  * By default, windows are decorated with a title bar, resize
2216  * controls, etc.  Some <link linkend="gtk-X11-arch">window
2217  * managers</link> allow GTK+ to disable these decorations, creating a
2218  * borderless window. If you set the decorated property to %FALSE
2219  * using this function, GTK+ will do its best to convince the window
2220  * manager not to decorate the window. Depending on the system, this
2221  * function may not have any effect when called on a window that is
2222  * already visible, so you should call it before calling gtk_window_show().
2223  *
2224  * On Windows, this function always works, since there's no window manager
2225  * policy involved.
2226  * 
2227  **/
2228 void
2229 gtk_window_set_decorated (GtkWindow *window,
2230                           gboolean   setting)
2231 {
2232   g_return_if_fail (GTK_IS_WINDOW (window));
2233
2234   setting = setting != FALSE;
2235
2236   if (setting == window->decorated)
2237     return;
2238
2239   window->decorated = setting;
2240   
2241   if (GTK_WIDGET (window)->window)
2242     {
2243       if (window->decorated)
2244         gdk_window_set_decorations (GTK_WIDGET (window)->window,
2245                                     GDK_DECOR_ALL);
2246       else
2247         gdk_window_set_decorations (GTK_WIDGET (window)->window,
2248                                     0);
2249     }
2250
2251   g_object_notify (G_OBJECT (window), "decorated");
2252 }
2253
2254 /**
2255  * gtk_window_get_decorated:
2256  * @window: a #GtkWindow
2257  *
2258  * Returns whether the window has been set to have decorations
2259  * such as a title bar via gtk_window_set_decorated().
2260  *
2261  * Return value: %TRUE if the window has been set to have decorations
2262  **/
2263 gboolean
2264 gtk_window_get_decorated (GtkWindow *window)
2265 {
2266   g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
2267
2268   return window->decorated;
2269 }
2270
2271 static GtkWindowIconInfo*
2272 get_icon_info (GtkWindow *window)
2273 {
2274   return g_object_get_data (G_OBJECT (window),
2275                             "gtk-window-icon-info");
2276 }
2277      
2278 static GtkWindowIconInfo*
2279 ensure_icon_info (GtkWindow *window)
2280 {
2281   GtkWindowIconInfo *info;
2282
2283   info = get_icon_info (window);
2284   
2285   if (info == NULL)
2286     {
2287       info = g_new0 (GtkWindowIconInfo, 1);
2288       g_object_set_data_full (G_OBJECT (window),
2289                               "gtk-window-icon-info",
2290                               info,
2291                               g_free);
2292     }
2293
2294   return info;
2295 }
2296
2297 typedef struct {
2298   guint serial;
2299   GdkPixmap *pixmap;
2300   GdkPixmap *mask;
2301 } ScreenIconInfo;
2302
2303 ScreenIconInfo *
2304 get_screen_icon_info (GdkScreen *screen)
2305 {
2306   ScreenIconInfo *info = g_object_get_data (G_OBJECT (screen), 
2307                                             "gtk-window-default-icon-pixmap");
2308   if (!info)
2309     {
2310       info = g_new0 (ScreenIconInfo, 1);
2311       g_object_set_data (G_OBJECT (screen), "gtk-window-default-icon-pixmap", info);
2312     }
2313
2314   if (info->serial != default_icon_serial)
2315     {
2316       if (info->pixmap)
2317         {
2318           g_object_remove_weak_pointer (G_OBJECT (info->pixmap), (gpointer*)&info->pixmap);
2319           info->pixmap = NULL;
2320         }
2321           
2322       if (info->mask)
2323         {
2324           g_object_remove_weak_pointer (G_OBJECT (info->mask), (gpointer*)&info->mask);
2325           info->mask = NULL;
2326         }
2327
2328       info->serial = default_icon_serial;
2329     }
2330   
2331   return info;
2332 }
2333
2334 static void
2335 get_pixmap_and_mask (GdkWindow          *window,
2336                      GtkWindowIconInfo  *parent_info,
2337                      gboolean            is_default_list,
2338                      GList              *icon_list,
2339                      GdkPixmap         **pmap_return,
2340                      GdkBitmap         **mask_return)
2341 {
2342   GdkScreen *screen = gdk_drawable_get_screen (window);
2343   ScreenIconInfo *default_icon_info = get_screen_icon_info (screen);
2344   GdkPixbuf *best_icon;
2345   GList *tmp_list;
2346   int best_size;
2347   
2348   *pmap_return = NULL;
2349   *mask_return = NULL;
2350   
2351   if (is_default_list &&
2352       default_icon_info->pixmap != NULL)
2353     {
2354       /* Use shared icon pixmap for all windows on this screen.
2355        */
2356       if (default_icon_info->pixmap)
2357         g_object_ref (default_icon_info->pixmap);
2358       if (default_icon_info->mask)
2359         g_object_ref (default_icon_info->mask);
2360
2361       *pmap_return = default_icon_info->pixmap;
2362       *mask_return = default_icon_info->mask;
2363     }
2364   else if (parent_info && parent_info->icon_pixmap)
2365     {
2366       if (parent_info->icon_pixmap)
2367         g_object_ref (parent_info->icon_pixmap);
2368       if (parent_info->icon_mask)
2369         g_object_ref (parent_info->icon_mask);
2370       
2371       *pmap_return = parent_info->icon_pixmap;
2372       *mask_return = parent_info->icon_mask;
2373     }
2374   else
2375     {
2376 #define IDEAL_SIZE 48
2377   
2378       best_size = G_MAXINT;
2379       best_icon = NULL;
2380       tmp_list = icon_list;
2381       while (tmp_list != NULL)
2382         {
2383           GdkPixbuf *pixbuf = tmp_list->data;
2384           int this;
2385       
2386           /* average width and height - if someone passes in a rectangular
2387            * icon they deserve what they get.
2388            */
2389           this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
2390           this /= 2;
2391       
2392           if (best_icon == NULL)
2393             {
2394               best_icon = pixbuf;
2395               best_size = this;
2396             }
2397           else
2398             {
2399               /* icon is better if it's 32 pixels or larger, and closer to
2400                * the ideal size than the current best.
2401                */
2402               if (this >= 32 &&
2403                   (ABS (best_size - IDEAL_SIZE) <
2404                    ABS (this - IDEAL_SIZE)))
2405                 {
2406                   best_icon = pixbuf;
2407                   best_size = this;
2408                 }
2409             }
2410
2411           tmp_list = tmp_list->next;
2412         }
2413
2414       if (best_icon)
2415         gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
2416                                                         gdk_screen_get_system_colormap (screen),
2417                                                         pmap_return,
2418                                                         mask_return,
2419                                                         128);
2420
2421       /* Save pmap/mask for others to use if appropriate */
2422       if (parent_info)
2423         {
2424           parent_info->icon_pixmap = *pmap_return;
2425           parent_info->icon_mask = *mask_return;
2426
2427           if (parent_info->icon_pixmap)
2428             g_object_ref (parent_info->icon_pixmap);
2429           if (parent_info->icon_mask)
2430             g_object_ref (parent_info->icon_mask);
2431         }
2432       else if (is_default_list)
2433         {
2434           default_icon_info->pixmap = *pmap_return;
2435           default_icon_info->mask = *mask_return;
2436
2437           if (default_icon_info->pixmap)
2438             g_object_add_weak_pointer (G_OBJECT (default_icon_info->pixmap),
2439                                        (gpointer*)&default_icon_info->pixmap);
2440           if (default_icon_info->mask) 
2441             g_object_add_weak_pointer (G_OBJECT (default_icon_info->mask),
2442                                        (gpointer*)&default_icon_info->mask);
2443         }
2444     }
2445 }
2446
2447 static void
2448 gtk_window_realize_icon (GtkWindow *window)
2449 {
2450   GtkWidget *widget;
2451   GtkWindowIconInfo *info;
2452   GList *icon_list;
2453   
2454   widget = GTK_WIDGET (window);
2455
2456   g_return_if_fail (widget->window != NULL);
2457
2458   /* no point setting an icon on override-redirect */
2459   if (window->type == GTK_WINDOW_POPUP)
2460     return;
2461
2462   icon_list = NULL;
2463   
2464   info = ensure_icon_info (window);
2465
2466   if (info->realized)
2467     return;
2468
2469   g_return_if_fail (info->icon_pixmap == NULL);
2470   g_return_if_fail (info->icon_mask == NULL);
2471   
2472   info->using_default_icon = FALSE;
2473   info->using_parent_icon = FALSE;
2474   
2475   icon_list = info->icon_list;
2476   
2477   /* Inherit from transient parent */
2478   if (icon_list == NULL && window->transient_parent)
2479     {
2480       icon_list = ensure_icon_info (window->transient_parent)->icon_list;
2481       if (icon_list)
2482         info->using_parent_icon = TRUE;
2483     }      
2484
2485   /* Inherit from default */
2486   if (icon_list == NULL)
2487     {
2488       icon_list = default_icon_list;
2489       if (icon_list)
2490         info->using_default_icon = TRUE;
2491     }
2492   
2493   gdk_window_set_icon_list (widget->window, icon_list);
2494
2495   get_pixmap_and_mask (widget->window,
2496                        info->using_parent_icon ? ensure_icon_info (window->transient_parent) : NULL,
2497                        info->using_default_icon,
2498                        icon_list,
2499                        &info->icon_pixmap,
2500                        &info->icon_mask);
2501   
2502   /* This is a slight ICCCM violation since it's a color pixmap not
2503    * a bitmap, but everyone does it.
2504    */
2505   gdk_window_set_icon (widget->window,
2506                        NULL,
2507                        info->icon_pixmap,
2508                        info->icon_mask);
2509
2510   info->realized = TRUE;
2511 }
2512
2513 static void
2514 gtk_window_unrealize_icon (GtkWindow *window)
2515 {
2516   GtkWindowIconInfo *info;
2517   GtkWidget *widget;
2518
2519   widget = GTK_WIDGET (window);
2520   
2521   info = get_icon_info (window);
2522
2523   if (info == NULL)
2524     return;
2525   
2526   if (info->icon_pixmap)
2527     g_object_unref (info->icon_pixmap);
2528
2529   if (info->icon_mask)
2530     g_object_unref (info->icon_mask);
2531
2532   info->icon_pixmap = NULL;
2533   info->icon_mask = NULL;
2534
2535   /* We don't clear the properties on the window, just figure the
2536    * window is going away.
2537    */
2538
2539   info->realized = FALSE;
2540 }
2541
2542 /**
2543  * gtk_window_set_icon_list:
2544  * @window: a #GtkWindow
2545  * @list: list of #GdkPixbuf
2546  *
2547  * Sets up the icon representing a #GtkWindow. The icon is used when
2548  * the window is minimized (also known as iconified).  Some window
2549  * managers or desktop environments may also place it in the window
2550  * frame, or display it in other contexts.
2551  *
2552  * gtk_window_set_icon_list() allows you to pass in the same icon in
2553  * several hand-drawn sizes. The list should contain the natural sizes
2554  * your icon is available in; that is, don't scale the image before
2555  * passing it to GTK+. Scaling is postponed until the last minute,
2556  * when the desired final size is known, to allow best quality.
2557  *
2558  * By passing several sizes, you may improve the final image quality
2559  * of the icon, by reducing or eliminating automatic image scaling.
2560  *
2561  * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
2562  * larger images (64x64, 128x128) if you have them.
2563  *
2564  * See also gtk_window_set_default_icon_list() to set the icon
2565  * for all windows in your application in one go.
2566  *
2567  * Note that transient windows (those who have been set transient for another
2568  * window using gtk_window_set_transient_for()) will inherit their
2569  * icon from their transient parent. So there's no need to explicitly
2570  * set the icon on transient windows.
2571  **/
2572 void
2573 gtk_window_set_icon_list (GtkWindow  *window,
2574                           GList      *list)
2575 {
2576   GtkWindowIconInfo *info;
2577
2578   g_return_if_fail (GTK_IS_WINDOW (window));
2579
2580   info = ensure_icon_info (window);
2581
2582   if (info->icon_list == list) /* check for NULL mostly */
2583     return;
2584
2585   g_list_foreach (info->icon_list,
2586                   (GFunc) g_object_unref, NULL);
2587
2588   g_list_free (info->icon_list);
2589
2590   info->icon_list = g_list_copy (list);
2591   g_list_foreach (info->icon_list,
2592                   (GFunc) g_object_ref, NULL);
2593
2594   g_object_notify (G_OBJECT (window), "icon");
2595   
2596   gtk_window_unrealize_icon (window);
2597   
2598   if (GTK_WIDGET_REALIZED (window))
2599     gtk_window_realize_icon (window);
2600
2601   /* We could try to update our transient children, but I don't think
2602    * it's really worth it. If we did it, the best way would probably
2603    * be to have children connect to notify::icon_list
2604    */
2605 }
2606
2607 /**
2608  * gtk_window_get_icon_list:
2609  * @window: a #GtkWindow
2610  * 
2611  * Retrieves the list of icons set by gtk_window_set_icon_list().
2612  * The list is copied, but the reference count on each
2613  * member won't be incremented.
2614  * 
2615  * Return value: copy of window's icon list
2616  **/
2617 GList*
2618 gtk_window_get_icon_list (GtkWindow  *window)
2619 {
2620   GtkWindowIconInfo *info;
2621   
2622   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2623
2624   info = get_icon_info (window);
2625
2626   if (info)
2627     return g_list_copy (info->icon_list);
2628   else
2629     return NULL;  
2630 }
2631
2632 /**
2633  * gtk_window_set_icon:
2634  * @window: a #GtkWindow
2635  * @icon: icon image, or %NULL
2636  * 
2637  * Sets up the icon representing a #GtkWindow. This icon is used when
2638  * the window is minimized (also known as iconified).  Some window
2639  * managers or desktop environments may also place it in the window
2640  * frame, or display it in other contexts.
2641  *
2642  * The icon should be provided in whatever size it was naturally
2643  * drawn; that is, don't scale the image before passing it to
2644  * GTK+. Scaling is postponed until the last minute, when the desired
2645  * final size is known, to allow best quality.
2646  *
2647  * If you have your icon hand-drawn in multiple sizes, use
2648  * gtk_window_set_icon_list(). Then the best size will be used.
2649  *
2650  * This function is equivalent to calling gtk_window_set_icon_list()
2651  * with a 1-element list.
2652  *
2653  * See also gtk_window_set_default_icon_list() to set the icon
2654  * for all windows in your application in one go.
2655  **/
2656 void
2657 gtk_window_set_icon (GtkWindow  *window,
2658                      GdkPixbuf  *icon)
2659 {
2660   GList *list;
2661   
2662   g_return_if_fail (GTK_IS_WINDOW (window));
2663   g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
2664
2665   list = NULL;
2666
2667   if (icon)
2668     list = g_list_append (list, icon);
2669   
2670   gtk_window_set_icon_list (window, list);
2671   g_list_free (list);  
2672 }
2673
2674 /**
2675  * gtk_window_get_icon:
2676  * @window: a #GtkWindow
2677  * 
2678  * Gets the value set by gtk_window_set_icon() (or if you've
2679  * called gtk_window_set_icon_list(), gets the first icon in
2680  * the icon list).
2681  * 
2682  * Return value: icon for window
2683  **/
2684 GdkPixbuf*
2685 gtk_window_get_icon (GtkWindow  *window)
2686 {
2687   GtkWindowIconInfo *info;
2688
2689   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2690
2691   info = get_icon_info (window);
2692   if (info && info->icon_list)
2693     return GDK_PIXBUF (info->icon_list->data);
2694   else
2695     return NULL;
2696 }
2697
2698 /* Load pixbuf, printing warning on failure if error == NULL
2699  */
2700 static GdkPixbuf *
2701 load_pixbuf_verbosely (const char *filename,
2702                        GError    **err)
2703 {
2704   GError *local_err = NULL;
2705   GdkPixbuf *pixbuf;
2706
2707   pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
2708
2709   if (!pixbuf)
2710     {
2711       if (err)
2712         *err = local_err;
2713       else
2714         {
2715           g_warning ("Error loading icon from file '%s':\n\t%s",
2716                      filename, local_err->message);
2717           g_error_free (local_err);
2718         }
2719     }
2720
2721   return pixbuf;
2722 }
2723
2724 /**
2725  * gtk_window_set_icon_from_file:
2726  * @window: a #GtkWindow
2727  * @filename: location of icon file
2728  * @err: location to store error, or %NULL.
2729  *
2730  * Sets the icon for @window.  
2731  * Warns on failure if @err is %NULL.
2732  *
2733  * This function is equivalent to calling gtk_window_set_icon()
2734  * with a pixbuf created by loading the image from @filename.
2735  *
2736  * Returns: %TRUE if setting the icon succeeded.
2737  *
2738  * Since: 2.2
2739  **/
2740 gboolean
2741 gtk_window_set_icon_from_file (GtkWindow   *window,
2742                                const gchar *filename,
2743                                GError     **err)
2744 {
2745   GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
2746
2747   if (pixbuf)
2748     {
2749       gtk_window_set_icon (window, pixbuf);
2750       g_object_unref (pixbuf);
2751       
2752       return TRUE;
2753     }
2754   else
2755     return FALSE;
2756 }
2757
2758 /**
2759  * gtk_window_set_default_icon_list:
2760  * @list: a list of #GdkPixbuf
2761  *
2762  * Sets an icon list to be used as fallback for windows that haven't
2763  * had gtk_window_set_icon_list() called on them to set up a
2764  * window-specific icon list. This function allows you to set up the
2765  * icon for all windows in your app at once.
2766  *
2767  * See gtk_window_set_icon_list() for more details.
2768  * 
2769  **/
2770 void
2771 gtk_window_set_default_icon_list (GList *list)
2772 {
2773   GList *toplevels;
2774   GList *tmp_list;
2775   if (list == default_icon_list)
2776     return;
2777
2778   /* Update serial so we don't used cached pixmaps/masks
2779    */
2780   default_icon_serial++;
2781   
2782   g_list_foreach (default_icon_list,
2783                   (GFunc) g_object_unref, NULL);
2784
2785   g_list_free (default_icon_list);
2786
2787   default_icon_list = g_list_copy (list);
2788   g_list_foreach (default_icon_list,
2789                   (GFunc) g_object_ref, NULL);
2790   
2791   /* Update all toplevels */
2792   toplevels = gtk_window_list_toplevels ();
2793   tmp_list = toplevels;
2794   while (tmp_list != NULL)
2795     {
2796       GtkWindowIconInfo *info;
2797       GtkWindow *w = tmp_list->data;
2798       
2799       info = get_icon_info (w);
2800       if (info && info->using_default_icon)
2801         {
2802           gtk_window_unrealize_icon (w);
2803           if (GTK_WIDGET_REALIZED (w))
2804             gtk_window_realize_icon (w);
2805         }
2806
2807       tmp_list = tmp_list->next;
2808     }
2809   g_list_free (toplevels);
2810 }
2811
2812 /**
2813  * gtk_window_set_default_icon:
2814  * @icon: the icon
2815  *
2816  * Sets an icon to be used as fallback for windows that haven't
2817  * had gtk_window_set_icon() called on them from a pixbuf.
2818  *
2819  * Since: 2.4
2820  **/
2821 void
2822 gtk_window_set_default_icon (GdkPixbuf *icon)
2823 {
2824   GList *list;
2825   
2826   g_return_if_fail (GDK_IS_PIXBUF (icon));
2827
2828   list = g_list_prepend (NULL, icon);
2829   gtk_window_set_default_icon_list (list);
2830   g_list_free (list);
2831 }
2832
2833 /**
2834  * gtk_window_set_default_icon_from_file:
2835  * @filename: location of icon file
2836  * @err: location to store error, or %NULL.
2837  *
2838  * Sets an icon to be used as fallback for windows that haven't
2839  * had gtk_window_set_icon_list() called on them from a file
2840  * on disk. Warns on failure if @err is %NULL.
2841  *
2842  * Returns: %TRUE if setting the icon succeeded.
2843  *
2844  * Since: 2.2
2845  **/
2846 gboolean
2847 gtk_window_set_default_icon_from_file (const gchar *filename,
2848                                        GError     **err)
2849 {
2850   GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
2851
2852   if (pixbuf)
2853     {
2854       gtk_window_set_default_icon (pixbuf);
2855       g_object_unref (pixbuf);
2856       
2857       return TRUE;
2858     }
2859   else
2860     return FALSE;
2861 }
2862
2863 /**
2864  * gtk_window_get_default_icon_list:
2865  * 
2866  * Gets the value set by gtk_window_set_default_icon_list().
2867  * The list is a copy and should be freed with g_list_free(),
2868  * but the pixbufs in the list have not had their reference count
2869  * incremented.
2870  * 
2871  * Return value: copy of default icon list 
2872  **/
2873 GList*
2874 gtk_window_get_default_icon_list (void)
2875 {
2876   return g_list_copy (default_icon_list);
2877 }
2878
2879 static void
2880 gtk_window_set_default_size_internal (GtkWindow    *window,
2881                                       gboolean      change_width,
2882                                       gint          width,
2883                                       gboolean      change_height,
2884                                       gint          height,
2885                                       gboolean      is_geometry)
2886 {
2887   GtkWindowGeometryInfo *info;
2888
2889   g_return_if_fail (change_width == FALSE || width >= -1);
2890   g_return_if_fail (change_height == FALSE || height >= -1);
2891
2892   info = gtk_window_get_geometry_info (window, TRUE);
2893
2894   g_object_freeze_notify (G_OBJECT (window));
2895
2896   info->default_is_geometry = is_geometry != FALSE;
2897
2898   if (change_width)
2899     {
2900       if (width == 0)
2901         width = 1;
2902
2903       if (width < 0)
2904         width = -1;
2905
2906       info->default_width = width;
2907
2908       g_object_notify (G_OBJECT (window), "default_width");
2909     }
2910
2911   if (change_height)
2912     {
2913       if (height == 0)
2914         height = 1;
2915
2916       if (height < 0)
2917         height = -1;
2918
2919       info->default_height = height;
2920       
2921       g_object_notify (G_OBJECT (window), "default_height");
2922     }
2923   
2924   g_object_thaw_notify (G_OBJECT (window));
2925   
2926   gtk_widget_queue_resize (GTK_WIDGET (window));
2927 }
2928
2929 /**
2930  * gtk_window_set_default_size:
2931  * @window: a #GtkWindow
2932  * @width: width in pixels, or -1 to unset the default width
2933  * @height: height in pixels, or -1 to unset the default height
2934  *
2935  * Sets the default size of a window. If the window's "natural" size
2936  * (its size request) is larger than the default, the default will be
2937  * ignored. More generally, if the default size does not obey the
2938  * geometry hints for the window (gtk_window_set_geometry_hints() can
2939  * be used to set these explicitly), the default size will be clamped
2940  * to the nearest permitted size.
2941  * 
2942  * Unlike gtk_widget_set_size_request(), which sets a size request for
2943  * a widget and thus would keep users from shrinking the window, this
2944  * function only sets the initial size, just as if the user had
2945  * resized the window themselves. Users can still shrink the window
2946  * again as they normally would. Setting a default size of -1 means to
2947  * use the "natural" default size (the size request of the window).
2948  *
2949  * For more control over a window's initial size and how resizing works,
2950  * investigate gtk_window_set_geometry_hints().
2951  *
2952  * For some uses, gtk_window_resize() is a more appropriate function.
2953  * gtk_window_resize() changes the current size of the window, rather
2954  * than the size to be used on initial display. gtk_window_resize() always
2955  * affects the window itself, not the geometry widget.
2956  *
2957  * The default size of a window only affects the first time a window is
2958  * shown; if a window is hidden and re-shown, it will remember the size
2959  * it had prior to hiding, rather than using the default size.
2960  *
2961  * Windows can't actually be 0x0 in size, they must be at least 1x1, but
2962  * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
2963  **/
2964 void       
2965 gtk_window_set_default_size (GtkWindow   *window,
2966                              gint         width,
2967                              gint         height)
2968 {
2969   g_return_if_fail (GTK_IS_WINDOW (window));
2970   g_return_if_fail (width >= -1);
2971   g_return_if_fail (height >= -1);
2972
2973   gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
2974 }
2975
2976 /**
2977  * gtk_window_get_default_size:
2978  * @window: a #GtkWindow
2979  * @width: location to store the default width, or %NULL
2980  * @height: location to store the default height, or %NULL
2981  *
2982  * Gets the default size of the window. A value of -1 for the width or
2983  * height indicates that a default size has not been explicitly set
2984  * for that dimension, so the "natural" size of the window will be
2985  * used.
2986  * 
2987  **/
2988 void
2989 gtk_window_get_default_size (GtkWindow *window,
2990                              gint      *width,
2991                              gint      *height)
2992 {
2993   GtkWindowGeometryInfo *info;
2994
2995   g_return_if_fail (GTK_IS_WINDOW (window));
2996
2997   info = gtk_window_get_geometry_info (window, FALSE);
2998
2999   if (width)
3000     *width = info ? info->default_width : -1;
3001
3002   if (height)
3003     *height = info ? info->default_height : -1;
3004 }
3005
3006 /**
3007  * gtk_window_resize:
3008  * @window: a #GtkWindow
3009  * @width: width in pixels to resize the window to
3010  * @height: height in pixels to resize the window to
3011  *
3012  * Resizes the window as if the user had done so, obeying geometry
3013  * constraints. The default geometry constraint is that windows may
3014  * not be smaller than their size request; to override this
3015  * constraint, call gtk_widget_set_size_request() to set the window's
3016  * request to a smaller value.
3017  *
3018  * If gtk_window_resize() is called before showing a window for the
3019  * first time, it overrides any default size set with
3020  * gtk_window_set_default_size().
3021  *
3022  * Windows may not be resized smaller than 1 by 1 pixels.
3023  * 
3024  **/
3025 void
3026 gtk_window_resize (GtkWindow *window,
3027                    gint       width,
3028                    gint       height)
3029 {
3030   GtkWindowGeometryInfo *info;
3031   
3032   g_return_if_fail (GTK_IS_WINDOW (window));
3033   g_return_if_fail (width > 0);
3034   g_return_if_fail (height > 0);
3035
3036   info = gtk_window_get_geometry_info (window, TRUE);
3037
3038   info->resize_width = width;
3039   info->resize_height = height;
3040
3041   gtk_widget_queue_resize (GTK_WIDGET (window));
3042 }
3043
3044 /**
3045  * gtk_window_get_size:
3046  * @window: a #GtkWindow
3047  * @width: return location for width, or %NULL
3048  * @height: return location for height, or %NULL
3049  *
3050  * Obtains the current size of @window. If @window is not onscreen,
3051  * it returns the size GTK+ will suggest to the <link
3052  * linkend="gtk-X11-arch">window manager</link> for the initial window
3053  * size (but this is not reliably the same as the size the window
3054  * manager will actually select). The size obtained by
3055  * gtk_window_get_size() is the last size received in a
3056  * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
3057  * rather than querying the X server for the size. As a result, if you
3058  * call gtk_window_resize() then immediately call
3059  * gtk_window_get_size(), the size won't have taken effect yet. After
3060  * the window manager processes the resize request, GTK+ receives
3061  * notification that the size has changed via a configure event, and
3062  * the size of the window gets updated.
3063  *
3064  * Note 1: Nearly any use of this function creates a race condition,
3065  * because the size of the window may change between the time that you
3066  * get the size and the time that you perform some action assuming
3067  * that size is the current size. To avoid race conditions, connect to
3068  * "configure_event" on the window and adjust your size-dependent
3069  * state to match the size delivered in the #GdkEventConfigure.
3070  *
3071  * Note 2: The returned size does <emphasis>not</emphasis> include the
3072  * size of the window manager decorations (aka the window frame or
3073  * border). Those are not drawn by GTK+ and GTK+ has no reliable
3074  * method of determining their size.
3075  *
3076  * Note 3: If you are getting a window size in order to position
3077  * the window onscreen, there may be a better way. The preferred
3078  * way is to simply set the window's semantic type with
3079  * gtk_window_set_type_hint(), which allows the window manager to
3080  * e.g. center dialogs. Also, if you set the transient parent of
3081  * dialogs with gtk_window_set_transient_for() window managers
3082  * will often center the dialog over its parent window. It's
3083  * much preferred to let the window manager handle these
3084  * things rather than doing it yourself, because all apps will
3085  * behave consistently and according to user prefs if the window
3086  * manager handles it. Also, the window manager can take the size
3087  * of the window decorations/border into account, while your
3088  * application cannot.
3089  *
3090  * In any case, if you insist on application-specified window
3091  * positioning, there's <emphasis>still</emphasis> a better way than
3092  * doing it yourself - gtk_window_set_position() will frequently
3093  * handle the details for you.
3094  * 
3095  **/
3096 void
3097 gtk_window_get_size (GtkWindow *window,
3098                      gint      *width,
3099                      gint      *height)
3100 {
3101   gint w, h;
3102   GtkWidget *widget;
3103   
3104   g_return_if_fail (GTK_IS_WINDOW (window));
3105
3106   widget = GTK_WIDGET (window);
3107   
3108   if (width == NULL && height == NULL)
3109     return;
3110
3111   if (GTK_WIDGET_MAPPED (window))
3112     {
3113       gdk_drawable_get_size (GTK_WIDGET (window)->window,
3114                              &w, &h);
3115     }
3116   else
3117     {
3118       GdkRectangle configure_request;
3119
3120       gtk_window_compute_configure_request (window,
3121                                             &configure_request,
3122                                             NULL, NULL);
3123
3124       w = configure_request.width;
3125       h = configure_request.height;
3126     }
3127   
3128   if (width)
3129     *width = w;
3130   if (height)
3131     *height = h;
3132 }
3133
3134 /**
3135  * gtk_window_move:
3136  * @window: a #GtkWindow
3137  * @x: X coordinate to move window to
3138  * @y: Y coordinate to move window to
3139  *
3140  * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
3141  * @window to the given position.  Window managers are free to ignore
3142  * this; most window managers ignore requests for initial window
3143  * positions (instead using a user-defined placement algorithm) and
3144  * honor requests after the window has already been shown.
3145  *
3146  * Note: the position is the position of the gravity-determined
3147  * reference point for the window. The gravity determines two things:
3148  * first, the location of the reference point in root window
3149  * coordinates; and second, which point on the window is positioned at
3150  * the reference point.
3151  *
3152  * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
3153  * point is simply the @x, @y supplied to gtk_window_move(). The
3154  * top-left corner of the window decorations (aka window frame or
3155  * border) will be placed at @x, @y.  Therefore, to position a window
3156  * at the top left of the screen, you want to use the default gravity
3157  * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
3158  *
3159  * To position a window at the bottom right corner of the screen, you
3160  * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
3161  * point is at @x + the window width and @y + the window height, and
3162  * the bottom-right corner of the window border will be placed at that
3163  * reference point. So, to place a window in the bottom right corner
3164  * you would first set gravity to south east, then write:
3165  * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
3166  * gdk_screen_height () - window_height)</literal>.
3167  *
3168  * The Extended Window Manager Hints specification at <ulink 
3169  * url="http://www.freedesktop.org/standards/wm-spec.html">
3170  * http://www.freedesktop.org/standards/wm-spec.html</ulink> has a 
3171  * nice table of gravities in the "implementation notes" section.
3172  *
3173  * The gtk_window_get_position() documentation may also be relevant.
3174  * 
3175  **/
3176 void
3177 gtk_window_move (GtkWindow *window,
3178                  gint       x,
3179                  gint       y)
3180 {
3181   GtkWindowGeometryInfo *info;
3182   GtkWidget *widget;
3183   
3184   g_return_if_fail (GTK_IS_WINDOW (window));
3185
3186   widget = GTK_WIDGET (window);
3187
3188   info = gtk_window_get_geometry_info (window, TRUE);  
3189   
3190   if (GTK_WIDGET_MAPPED (window))
3191     {
3192       /* we have now sent a request with this position
3193        * with currently-active constraints, so toggle flag.
3194        */
3195       info->position_constraints_changed = FALSE;
3196
3197       /* we only constrain if mapped - if not mapped,
3198        * then gtk_window_compute_configure_request()
3199        * will apply the constraints later, and we
3200        * don't want to lose information about
3201        * what position the user set before then.
3202        * i.e. if you do a move() then turn off POS_CENTER
3203        * then show the window, your move() will work.
3204        */
3205       gtk_window_constrain_position (window,
3206                                      widget->allocation.width,
3207                                      widget->allocation.height,
3208                                      &x, &y);
3209       
3210       /* Note that this request doesn't go through our standard request
3211        * framework, e.g. doesn't increment configure_request_count,
3212        * doesn't set info->last, etc.; that's because
3213        * we don't save the info needed to arrive at this same request
3214        * again.
3215        *
3216        * To gtk_window_move_resize(), this will end up looking exactly
3217        * the same as the position being changed by the window
3218        * manager.
3219        */
3220       
3221       /* FIXME are we handling gravity properly for framed windows? */
3222       if (window->frame)
3223         gdk_window_move (window->frame,
3224                          x - window->frame_left,
3225                          y - window->frame_top);
3226       else
3227         gdk_window_move (GTK_WIDGET (window)->window,
3228                          x, y);
3229     }
3230   else
3231     {
3232       /* Save this position to apply on mapping */
3233       info->initial_x = x;
3234       info->initial_y = y;
3235       info->initial_pos_set = TRUE;
3236     }
3237 }
3238
3239 /**
3240  * gtk_window_get_position:
3241  * @window: a #GtkWindow
3242  * @root_x: return location for X coordinate of gravity-determined reference p\oint
3243  * @root_y: return location for Y coordinate of gravity-determined reference p\oint
3244  *
3245  * This function returns the position you need to pass to
3246  * gtk_window_move() to keep @window in its current position.  This
3247  * means that the meaning of the returned value varies with window
3248  * gravity. See gtk_window_move() for more details.
3249  * 
3250  * If you haven't changed the window gravity, its gravity will be
3251  * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
3252  * gets the position of the top-left corner of the window manager
3253  * frame for the window. gtk_window_move() sets the position of this
3254  * same top-left corner.
3255  *
3256  * gtk_window_get_position() is not 100% reliable because the X Window System
3257  * does not specify a way to obtain the geometry of the
3258  * decorations placed on a window by the window manager.
3259  * Thus GTK+ is using a "best guess" that works with most
3260  * window managers.
3261  *
3262  * Moreover, nearly all window managers are historically broken with
3263  * respect to their handling of window gravity. So moving a window to
3264  * its current position as returned by gtk_window_get_position() tends
3265  * to result in moving the window slightly. Window managers are
3266  * slowly getting better over time.
3267  *
3268  * If a window has gravity #GDK_GRAVITY_STATIC the window manager
3269  * frame is not relevant, and thus gtk_window_get_position() will
3270  * always produce accurate results. However you can't use static
3271  * gravity to do things like place a window in a corner of the screen,
3272  * because static gravity ignores the window manager decorations.
3273  *
3274  * If you are saving and restoring your application's window
3275  * positions, you should know that it's impossible for applications to
3276  * do this without getting it somewhat wrong because applications do
3277  * not have sufficient knowledge of window manager state. The Correct
3278  * Mechanism is to support the session management protocol (see the
3279  * "GnomeClient" object in the GNOME libraries for example) and allow
3280  * the window manager to save your window sizes and positions.
3281  * 
3282  **/
3283
3284 void
3285 gtk_window_get_position (GtkWindow *window,
3286                          gint      *root_x,
3287                          gint      *root_y)
3288 {
3289   GtkWidget *widget;
3290
3291   g_return_if_fail (GTK_IS_WINDOW (window));
3292
3293   widget = GTK_WIDGET (window);
3294   
3295   if (window->gravity == GDK_GRAVITY_STATIC)
3296     {
3297       if (GTK_WIDGET_MAPPED (widget))
3298         {
3299           /* This does a server round-trip, which is sort of wrong;
3300            * but a server round-trip is inevitable for
3301            * gdk_window_get_frame_extents() in the usual
3302            * NorthWestGravity case below, so not sure what else to
3303            * do. We should likely be consistent about whether we get
3304            * the client-side info or the server-side info.
3305            */
3306           gdk_window_get_origin (widget->window, root_x, root_y);
3307         }
3308       else
3309         {
3310           GdkRectangle configure_request;
3311           
3312           gtk_window_compute_configure_request (window,
3313                                                 &configure_request,
3314                                                 NULL, NULL);
3315           
3316           *root_x = configure_request.x;
3317           *root_y = configure_request.y;
3318         }
3319     }
3320   else
3321     {
3322       GdkRectangle frame_extents;
3323       
3324       gint x, y;
3325       gint w, h;
3326       
3327       if (GTK_WIDGET_MAPPED (widget))
3328         {
3329           if (window->frame)
3330             gdk_window_get_frame_extents (window->frame, &frame_extents);
3331           else
3332             gdk_window_get_frame_extents (widget->window, &frame_extents);
3333           x = frame_extents.x;
3334           y = frame_extents.y;
3335           gtk_window_get_size (window, &w, &h);
3336         }
3337       else
3338         {
3339           /* We just say the frame has 0 size on all sides.
3340            * Not sure what else to do.
3341            */             
3342           gtk_window_compute_configure_request (window,
3343                                                 &frame_extents,
3344                                                 NULL, NULL);
3345           x = frame_extents.x;
3346           y = frame_extents.y;
3347           w = frame_extents.width;
3348           h = frame_extents.height;
3349         }
3350       
3351       switch (window->gravity)
3352         {
3353         case GDK_GRAVITY_NORTH:
3354         case GDK_GRAVITY_CENTER:
3355         case GDK_GRAVITY_SOUTH:
3356           /* Find center of frame. */
3357           x += frame_extents.width / 2;
3358           /* Center client window on that point. */
3359           x -= w / 2;
3360           break;
3361
3362         case GDK_GRAVITY_SOUTH_EAST:
3363         case GDK_GRAVITY_EAST:
3364         case GDK_GRAVITY_NORTH_EAST:
3365           /* Find right edge of frame */
3366           x += frame_extents.width;
3367           /* Align left edge of client at that point. */
3368           x -= w;
3369           break;
3370         default:
3371           break;
3372         }
3373
3374       switch (window->gravity)
3375         {
3376         case GDK_GRAVITY_WEST:
3377         case GDK_GRAVITY_CENTER:
3378         case GDK_GRAVITY_EAST:
3379           /* Find center of frame. */
3380           y += frame_extents.height / 2;
3381           /* Center client window there. */
3382           y -= h / 2;
3383           break;
3384         case GDK_GRAVITY_SOUTH_WEST:
3385         case GDK_GRAVITY_SOUTH:
3386         case GDK_GRAVITY_SOUTH_EAST:
3387           /* Find south edge of frame */
3388           y += frame_extents.height;
3389           /* Place bottom edge of client there */
3390           y -= h;
3391           break;
3392         default:
3393           break;
3394         }
3395       
3396       if (root_x)
3397         *root_x = x;
3398       if (root_y)
3399         *root_y = y;
3400     }
3401 }
3402
3403 /**
3404  * gtk_window_reshow_with_initial_size:
3405  * @window: a #GtkWindow
3406  * 
3407  * Hides @window, then reshows it, resetting the
3408  * default size and position of the window. Used
3409  * by GUI builders only.
3410  **/
3411 void
3412 gtk_window_reshow_with_initial_size (GtkWindow *window)
3413 {
3414   GtkWidget *widget;
3415   
3416   g_return_if_fail (GTK_IS_WINDOW (window));
3417
3418   widget = GTK_WIDGET (window);
3419   
3420   gtk_widget_hide (widget);
3421   gtk_widget_unrealize (widget);
3422   gtk_widget_show (widget);
3423 }
3424
3425 static void
3426 gtk_window_destroy (GtkObject *object)
3427 {
3428   GtkWindow *window = GTK_WINDOW (object);
3429   
3430   if (window->transient_parent)
3431     gtk_window_set_transient_for (window, NULL);
3432
3433   /* frees the icons */
3434   gtk_window_set_icon_list (window, NULL);
3435   
3436   if (window->has_user_ref_count)
3437     {
3438       window->has_user_ref_count = FALSE;
3439       g_object_unref (window);
3440     }
3441
3442   if (window->group)
3443     gtk_window_group_remove_window (window->group, window);
3444
3445    gtk_window_free_key_hash (window);
3446
3447    GTK_OBJECT_CLASS (parent_class)->destroy (object);
3448 }
3449
3450 static gboolean
3451 gtk_window_mnemonic_hash_remove (gpointer       key,
3452                                  gpointer       value,
3453                                  gpointer       user)
3454 {
3455   GtkWindowMnemonic *mnemonic = key;
3456   GtkWindow *window = user;
3457
3458   if (mnemonic->window == window)
3459     {
3460       if (mnemonic->targets)
3461         {
3462           gchar *name = gtk_accelerator_name (mnemonic->keyval, 0);
3463
3464           g_warning ("mnemonic \"%s\" wasn't removed for widget (%p)",
3465                      name, mnemonic->targets->data);
3466           g_free (name);
3467         }
3468       g_slist_free (mnemonic->targets);
3469       g_free (mnemonic);
3470       
3471       return TRUE;
3472     }
3473   return FALSE;
3474 }
3475
3476 static void
3477 gtk_window_finalize (GObject *object)
3478 {
3479   GtkWindow *window = GTK_WINDOW (object);
3480
3481   toplevel_list = g_slist_remove (toplevel_list, window);
3482
3483   g_free (window->title);
3484   g_free (window->wmclass_name);
3485   g_free (window->wmclass_class);
3486   g_free (window->wm_role);
3487
3488   g_hash_table_foreach_remove (mnemonic_hash_table,
3489                                gtk_window_mnemonic_hash_remove,
3490                                window);
3491   if (window->geometry_info)
3492     {
3493       if (window->geometry_info->widget)
3494         g_signal_handlers_disconnect_by_func (window->geometry_info->widget,
3495                                               gtk_widget_destroyed,
3496                                               &window->geometry_info->widget);
3497       g_free (window->geometry_info);
3498     }
3499
3500   if (window->keys_changed_handler)
3501     {
3502       g_source_remove (window->keys_changed_handler);
3503       window->keys_changed_handler = 0;
3504     }
3505
3506   G_OBJECT_CLASS (parent_class)->finalize (object);
3507 }
3508
3509 static void
3510 gtk_window_show (GtkWidget *widget)
3511 {
3512   GtkWindow *window = GTK_WINDOW (widget);
3513   GtkContainer *container = GTK_CONTAINER (window);
3514   gboolean need_resize;
3515
3516   GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
3517   
3518   need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
3519   container->need_resize = FALSE;
3520
3521   if (need_resize)
3522     {
3523       GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
3524       GtkAllocation allocation = { 0, 0 };
3525       GdkRectangle configure_request;
3526       GdkGeometry new_geometry;
3527       guint new_flags;
3528       gboolean was_realized;
3529
3530       /* We are going to go ahead and perform this configure request
3531        * and then emulate a configure notify by going ahead and
3532        * doing a size allocate. Sort of a synchronous
3533        * mini-copy of gtk_window_move_resize() here.
3534        */
3535       gtk_window_compute_configure_request (window,
3536                                             &configure_request,
3537                                             &new_geometry,
3538                                             &new_flags);
3539       
3540       /* We update this because we are going to go ahead
3541        * and gdk_window_resize() below, rather than
3542        * queuing it.
3543        */
3544       info->last.configure_request.width = configure_request.width;
3545       info->last.configure_request.height = configure_request.height;
3546       
3547       /* and allocate the window - this is normally done
3548        * in move_resize in response to configure notify
3549        */
3550       allocation.width  = configure_request.width;
3551       allocation.height = configure_request.height;
3552       gtk_widget_size_allocate (widget, &allocation);
3553
3554       /* Then we guarantee we have a realize */
3555       was_realized = FALSE;
3556       if (!GTK_WIDGET_REALIZED (widget))
3557         {
3558           gtk_widget_realize (widget);
3559           was_realized = TRUE;
3560         }
3561
3562       /* Must be done after the windows are realized,
3563        * so that the decorations can be read
3564        */
3565       gtk_decorated_window_calculate_frame_size (window);
3566
3567       /* We only send configure request if we didn't just finish
3568        * creating the window; if we just created the window
3569        * then we created it with widget->allocation anyhow.
3570        */
3571       if (!was_realized)
3572         gdk_window_resize (widget->window,
3573                            configure_request.width,
3574                            configure_request.height);
3575     }
3576   
3577   gtk_container_check_resize (container);
3578
3579   gtk_widget_map (widget);
3580
3581   /* Try to make sure that we have some focused widget
3582    */
3583 #ifdef GDK_WINDOWING_X11
3584   if (!window->focus_widget && !GTK_IS_PLUG (window))
3585 #else
3586   if (!window->focus_widget)
3587 #endif
3588     gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD);
3589   
3590   if (window->modal)
3591     gtk_grab_add (widget);
3592 }
3593
3594 static void
3595 gtk_window_hide (GtkWidget *widget)
3596 {
3597   GtkWindow *window = GTK_WINDOW (widget);
3598
3599   GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
3600   gtk_widget_unmap (widget);
3601
3602   if (window->modal)
3603     gtk_grab_remove (widget);
3604 }
3605
3606 static void
3607 gtk_window_map (GtkWidget *widget)
3608 {
3609   GtkWindow *window = GTK_WINDOW (widget);
3610   GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
3611   GdkWindow *toplevel;
3612
3613   GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
3614
3615   if (window->bin.child &&
3616       GTK_WIDGET_VISIBLE (window->bin.child) &&
3617       !GTK_WIDGET_MAPPED (window->bin.child))
3618     gtk_widget_map (window->bin.child);
3619
3620   if (window->frame)
3621     toplevel = window->frame;
3622   else
3623     toplevel = widget->window;
3624   
3625   if (window->maximize_initially)
3626     gdk_window_maximize (toplevel);
3627   else
3628     gdk_window_unmaximize (toplevel);
3629   
3630   if (window->stick_initially)
3631     gdk_window_stick (toplevel);
3632   else
3633     gdk_window_unstick (toplevel);
3634   
3635   if (window->iconify_initially)
3636     gdk_window_iconify (toplevel);
3637   else
3638     gdk_window_deiconify (toplevel);
3639
3640   if (priv->fullscreen_initially)
3641     gdk_window_fullscreen (toplevel);
3642   else
3643     gdk_window_unfullscreen (toplevel);
3644   
3645   gdk_window_set_keep_above (toplevel, priv->above_initially);
3646
3647   gdk_window_set_keep_below (toplevel, priv->below_initially);
3648
3649   /* No longer use the default settings */
3650   window->need_default_size = FALSE;
3651   window->need_default_position = FALSE;
3652   
3653   gdk_window_show (widget->window);
3654
3655   if (window->frame)
3656     gdk_window_show (window->frame);
3657
3658   if (!disable_startup_notification &&
3659       !sent_startup_notification)
3660     {
3661       sent_startup_notification = TRUE;
3662       gdk_notify_startup_complete ();
3663     }
3664 }
3665
3666 static void
3667 gtk_window_unmap (GtkWidget *widget)
3668 {
3669   GtkWindow *window = GTK_WINDOW (widget);
3670   GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (widget);
3671   GtkWindowGeometryInfo *info;    
3672   GdkWindowState state;
3673
3674   GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
3675   if (window->frame)
3676     gdk_window_withdraw (window->frame);
3677   else 
3678     gdk_window_withdraw (widget->window);
3679   
3680   window->configure_request_count = 0;
3681   window->configure_notify_received = FALSE;
3682
3683   /* on unmap, we reset the default positioning of the window,
3684    * so it's placed again, but we don't reset the default
3685    * size of the window, so it's remembered.
3686    */
3687   window->need_default_position = TRUE;
3688
3689   info = gtk_window_get_geometry_info (window, FALSE);
3690   if (info)
3691     {
3692       info->initial_pos_set = FALSE;
3693       info->position_constraints_changed = FALSE;
3694     }
3695
3696   state = gdk_window_get_state (widget->window);
3697   window->iconify_initially = state & GDK_WINDOW_STATE_ICONIFIED;
3698   window->maximize_initially = state & GDK_WINDOW_STATE_MAXIMIZED;
3699   window->stick_initially = state & GDK_WINDOW_STATE_STICKY;
3700   priv->above_initially = state & GDK_WINDOW_STATE_ABOVE;
3701   priv->below_initially = state & GDK_WINDOW_STATE_BELOW;
3702 }
3703
3704 static void
3705 gtk_window_realize (GtkWidget *widget)
3706 {
3707   GtkWindow *window;
3708   GdkWindow *parent_window;
3709   GdkWindowAttr attributes;
3710   gint attributes_mask;
3711   
3712   window = GTK_WINDOW (widget);
3713
3714   /* ensure widget tree is properly size allocated */
3715   if (widget->allocation.x == -1 &&
3716       widget->allocation.y == -1 &&
3717       widget->allocation.width == 1 &&
3718       widget->allocation.height == 1)
3719     {
3720       GtkRequisition requisition;
3721       GtkAllocation allocation = { 0, 0, 200, 200 };
3722
3723       gtk_widget_size_request (widget, &requisition);
3724       if (requisition.width || requisition.height)
3725         {
3726           /* non-empty window */
3727           allocation.width = requisition.width;
3728           allocation.height = requisition.height;
3729         }
3730       gtk_widget_size_allocate (widget, &allocation);
3731       
3732       _gtk_container_queue_resize (GTK_CONTAINER (widget));
3733
3734       g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
3735     }
3736   
3737   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
3738   
3739   switch (window->type)
3740     {
3741     case GTK_WINDOW_TOPLEVEL:
3742       attributes.window_type = GDK_WINDOW_TOPLEVEL;
3743       break;
3744     case GTK_WINDOW_POPUP:
3745       attributes.window_type = GDK_WINDOW_TEMP;
3746       break;
3747     default:
3748       g_warning (G_STRLOC": Unknown window type %d!", window->type);
3749       break;
3750     }
3751    
3752   attributes.title = window->title;
3753   attributes.wmclass_name = window->wmclass_name;
3754   attributes.wmclass_class = window->wmclass_class;
3755   attributes.wclass = GDK_INPUT_OUTPUT;
3756   attributes.visual = gtk_widget_get_visual (widget);
3757   attributes.colormap = gtk_widget_get_colormap (widget);
3758
3759   if (window->has_frame)
3760     {
3761       attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
3762       attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
3763       attributes.event_mask = (GDK_EXPOSURE_MASK |
3764                                GDK_KEY_PRESS_MASK |
3765                                GDK_ENTER_NOTIFY_MASK |
3766                                GDK_LEAVE_NOTIFY_MASK |
3767                                GDK_FOCUS_CHANGE_MASK |
3768                                GDK_STRUCTURE_MASK |
3769                                GDK_BUTTON_MOTION_MASK |
3770                                GDK_POINTER_MOTION_HINT_MASK |
3771                                GDK_BUTTON_PRESS_MASK |
3772                                GDK_BUTTON_RELEASE_MASK);
3773       
3774       attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
3775       
3776       window->frame = gdk_window_new (gtk_widget_get_root_window (widget),
3777                                       &attributes, attributes_mask);
3778                                                  
3779       gdk_window_set_user_data (window->frame, widget);
3780       
3781       attributes.window_type = GDK_WINDOW_CHILD;
3782       attributes.x = window->frame_left;
3783       attributes.y = window->frame_top;
3784     
3785       attributes_mask = GDK_WA_X | GDK_WA_Y;
3786
3787       parent_window = window->frame;
3788     }
3789   else
3790     {
3791       attributes_mask = 0;
3792       parent_window = gtk_widget_get_root_window (widget);
3793     }
3794   
3795   attributes.width = widget->allocation.width;
3796   attributes.height = widget->allocation.height;
3797   attributes.event_mask = gtk_widget_get_events (widget);
3798   attributes.event_mask |= (GDK_EXPOSURE_MASK |
3799                             GDK_KEY_PRESS_MASK |
3800                             GDK_KEY_RELEASE_MASK |
3801                             GDK_ENTER_NOTIFY_MASK |
3802                             GDK_LEAVE_NOTIFY_MASK |
3803                             GDK_FOCUS_CHANGE_MASK |
3804                             GDK_STRUCTURE_MASK);
3805
3806   attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
3807   attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
3808   attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
3809   
3810   widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
3811     
3812   gdk_window_set_user_data (widget->window, window);
3813       
3814   widget->style = gtk_style_attach (widget->style, widget->window);
3815   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
3816   if (window->frame)
3817     gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
3818
3819   /* This is a bad hack to set the window background. */
3820   gtk_window_paint (widget, NULL);
3821   
3822   if (window->transient_parent &&
3823       GTK_WIDGET_REALIZED (window->transient_parent))
3824     gdk_window_set_transient_for (widget->window,
3825                                   GTK_WIDGET (window->transient_parent)->window);
3826
3827   if (window->wm_role)
3828     gdk_window_set_role (widget->window, window->wm_role);
3829   
3830   if (!window->decorated)
3831     gdk_window_set_decorations (widget->window, 0);
3832
3833   gdk_window_set_type_hint (widget->window, window->type_hint);
3834
3835   if (gtk_window_get_skip_pager_hint (window))
3836     {
3837       g_print ("setting skip pager when realizing\n");
3838     gdk_window_set_skip_pager_hint (widget->window, TRUE);
3839     }
3840
3841   if (gtk_window_get_skip_taskbar_hint (window))
3842     gdk_window_set_skip_taskbar_hint (widget->window, TRUE);
3843   
3844   if (window->modal)
3845     gdk_window_set_modal_hint (widget->window, TRUE);
3846   else
3847     gdk_window_set_modal_hint (widget->window, FALSE);
3848
3849   /* Icons */
3850   gtk_window_realize_icon (window);
3851 }
3852
3853 static void
3854 gtk_window_unrealize (GtkWidget *widget)
3855 {
3856   GtkWindow *window;
3857   GtkWindowGeometryInfo *info;
3858
3859   window = GTK_WINDOW (widget);
3860
3861   /* On unrealize, we reset the size of the window such
3862    * that we will re-apply the default sizing stuff
3863    * next time we show the window.
3864    *
3865    * Default positioning is reset on unmap, instead of unrealize.
3866    */
3867   window->need_default_size = TRUE;
3868   info = gtk_window_get_geometry_info (window, FALSE);
3869   if (info)
3870     {
3871       info->resize_width = -1;
3872       info->resize_height = -1;
3873       info->last.configure_request.x = 0;
3874       info->last.configure_request.y = 0;
3875       info->last.configure_request.width = -1;
3876       info->last.configure_request.height = -1;
3877       /* be sure we reset geom hints on re-realize */
3878       info->last.flags = 0;
3879     }
3880   
3881   if (window->frame)
3882     {
3883       gdk_window_set_user_data (window->frame, NULL);
3884       gdk_window_destroy (window->frame);
3885       window->frame = NULL;
3886     }
3887
3888   /* Icons */
3889   gtk_window_unrealize_icon (window);
3890   
3891   (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
3892 }
3893
3894 static void
3895 gtk_window_size_request (GtkWidget      *widget,
3896                          GtkRequisition *requisition)
3897 {
3898   GtkWindow *window;
3899   GtkBin *bin;
3900
3901   window = GTK_WINDOW (widget);
3902   bin = GTK_BIN (window);
3903   
3904   requisition->width = GTK_CONTAINER (window)->border_width * 2;
3905   requisition->height = GTK_CONTAINER (window)->border_width * 2;
3906
3907   if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
3908     {
3909       GtkRequisition child_requisition;
3910       
3911       gtk_widget_size_request (bin->child, &child_requisition);
3912
3913       requisition->width += child_requisition.width;
3914       requisition->height += child_requisition.height;
3915     }
3916 }
3917
3918 static void
3919 gtk_window_size_allocate (GtkWidget     *widget,
3920                           GtkAllocation *allocation)
3921 {
3922   GtkWindow *window;
3923   GtkAllocation child_allocation;
3924
3925   window = GTK_WINDOW (widget);
3926   widget->allocation = *allocation;
3927
3928   if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
3929     {
3930       child_allocation.x = GTK_CONTAINER (window)->border_width;
3931       child_allocation.y = GTK_CONTAINER (window)->border_width;
3932       child_allocation.width =
3933         MAX (1, (gint)allocation->width - child_allocation.x * 2);
3934       child_allocation.height =
3935         MAX (1, (gint)allocation->height - child_allocation.y * 2);
3936
3937       gtk_widget_size_allocate (window->bin.child, &child_allocation);
3938     }
3939
3940   if (GTK_WIDGET_REALIZED (widget) && window->frame)
3941     {
3942       gdk_window_resize (window->frame,
3943                          allocation->width + window->frame_left + window->frame_right,
3944                          allocation->height + window->frame_top + window->frame_bottom);
3945     }
3946 }
3947
3948 static gint
3949 gtk_window_event (GtkWidget *widget, GdkEvent *event)
3950 {
3951   GtkWindow *window;
3952   gboolean return_val;
3953
3954   window = GTK_WINDOW (widget);
3955
3956   if (window->frame && (event->any.window == window->frame))
3957     {
3958       if ((event->type != GDK_KEY_PRESS) &&
3959           (event->type != GDK_KEY_RELEASE) &&
3960           (event->type != GDK_FOCUS_CHANGE))
3961         {
3962           g_signal_stop_emission_by_name (widget, "event");
3963           return_val = FALSE;
3964           g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
3965           return TRUE;
3966         }
3967       else
3968         {
3969           g_object_unref (event->any.window);
3970           event->any.window = g_object_ref (widget->window);
3971         }
3972     }
3973
3974   return FALSE;
3975 }
3976
3977 static gboolean
3978 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
3979 {
3980   GdkEventConfigure *configure_event;
3981   GdkRectangle rect;
3982
3983   switch (event->type)
3984     {
3985     case GDK_CONFIGURE:
3986       configure_event = (GdkEventConfigure *)event;
3987       
3988       /* Invalidate the decorations */
3989       rect.x = 0;
3990       rect.y = 0;
3991       rect.width = configure_event->width;
3992       rect.height = configure_event->height;
3993       
3994       gdk_window_invalidate_rect (window->frame, &rect, FALSE);
3995
3996       /* Pass on the (modified) configure event */
3997       configure_event->width -= window->frame_left + window->frame_right;
3998       configure_event->height -= window->frame_top + window->frame_bottom;
3999       return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
4000       break;
4001     default:
4002       break;
4003     }
4004   return FALSE;
4005 }
4006
4007 static gint
4008 gtk_window_configure_event (GtkWidget         *widget,
4009                             GdkEventConfigure *event)
4010 {
4011   GtkWindow *window = GTK_WINDOW (widget);
4012   gboolean expected_reply = window->configure_request_count > 0;
4013
4014   /* window->configure_request_count incremented for each 
4015    * configure request, and decremented to a min of 0 for
4016    * each configure notify.
4017    *
4018    * All it means is that we know we will get at least
4019    * window->configure_request_count more configure notifies.
4020    * We could get more configure notifies than that; some
4021    * of the configure notifies we get may be unrelated to
4022    * the configure requests. But we will get at least
4023    * window->configure_request_count notifies.
4024    */
4025
4026   if (window->configure_request_count > 0)
4027     window->configure_request_count -= 1;
4028   
4029   /* As an optimization, we avoid a resize when possible.
4030    *
4031    * The only times we can avoid a resize are:
4032    *   - we know only the position changed, not the size
4033    *   - we know we have made more requests and so will get more
4034    *     notifies and can wait to resize when we get them
4035    */
4036   
4037   if (!expected_reply &&
4038       (widget->allocation.width == event->width &&
4039        widget->allocation.height == event->height))
4040     return TRUE;
4041
4042   /*
4043    * If we do need to resize, we do that by:
4044    *   - filling in widget->allocation with the new size
4045    *   - setting configure_notify_received to TRUE
4046    *     for use in gtk_window_move_resize()
4047    *   - queueing a resize, leading to invocation of
4048    *     gtk_window_move_resize() in an idle handler
4049    *
4050    */
4051   
4052   window->configure_notify_received = TRUE;
4053   
4054   widget->allocation.width = event->width;
4055   widget->allocation.height = event->height;
4056   
4057   _gtk_container_queue_resize (GTK_CONTAINER (widget));
4058   
4059   return TRUE;
4060 }
4061
4062 /* the accel_key and accel_mods fields of the key have to be setup
4063  * upon calling this function. it'll then return whether that key
4064  * is at all used as accelerator, and if so will OR in the
4065  * accel_flags member of the key.
4066  */
4067 gboolean
4068 _gtk_window_query_nonaccels (GtkWindow      *window,
4069                              guint           accel_key,
4070                              GdkModifierType accel_mods)
4071 {
4072   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
4073
4074   /* movement keys are considered locked accels */
4075   if (!accel_mods)
4076     {
4077       static const guint bindings[] = {
4078         GDK_space, GDK_KP_Space, GDK_Return, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
4079         GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
4080       };
4081       guint i;
4082       
4083       for (i = 0; i < G_N_ELEMENTS (bindings); i++)
4084         if (bindings[i] == accel_key)
4085           return TRUE;
4086     }
4087
4088   /* mnemonics are considered locked accels */
4089   if (accel_mods == window->mnemonic_modifier)
4090     {
4091       GtkWindowMnemonic mkey;
4092
4093       mkey.window = window;
4094       mkey.keyval = accel_key;
4095       if (g_hash_table_lookup (mnemonic_hash_table, &mkey))
4096         return TRUE;
4097     }
4098
4099   return FALSE;
4100 }
4101
4102 static gint
4103 gtk_window_key_press_event (GtkWidget   *widget,
4104                             GdkEventKey *event)
4105 {
4106   GtkWindow *window;
4107   GtkWidget *focus;
4108   gboolean handled;
4109
4110   window = GTK_WINDOW (widget);
4111
4112   handled = FALSE;
4113
4114   /* Check for mnemonics and accelerators
4115    */
4116   if (!handled)
4117     handled = _gtk_window_activate_key (window, event);
4118
4119   if (!handled)
4120     {
4121       focus = window->focus_widget;
4122       if (focus)
4123         g_object_ref (focus);
4124       
4125       while (!handled &&
4126              focus && focus != widget &&
4127              gtk_widget_get_toplevel (focus) == widget)
4128         {
4129           GtkWidget *parent;
4130           
4131           if (GTK_WIDGET_IS_SENSITIVE (focus))
4132             handled = gtk_widget_event (focus, (GdkEvent*) event);
4133           
4134           parent = focus->parent;
4135           if (parent)
4136             g_object_ref (parent);
4137           
4138           g_object_unref (focus);
4139           
4140           focus = parent;
4141         }
4142
4143       if (focus)
4144         g_object_unref (focus);
4145     }
4146
4147   /* Chain up, invokes binding set */
4148   if (!handled && GTK_WIDGET_CLASS (parent_class)->key_press_event)
4149     handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
4150
4151   return handled;
4152 }
4153
4154 static gint
4155 gtk_window_key_release_event (GtkWidget   *widget,
4156                               GdkEventKey *event)
4157 {
4158   GtkWindow *window;
4159   gint handled;
4160   
4161   window = GTK_WINDOW (widget);
4162   handled = FALSE;
4163   if (window->focus_widget &&
4164       window->focus_widget != widget &&
4165       GTK_WIDGET_SENSITIVE (window->focus_widget))
4166     {
4167       handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
4168     }
4169
4170   if (!handled && GTK_WIDGET_CLASS (parent_class)->key_release_event)
4171     handled = GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
4172
4173   return handled;
4174 }
4175
4176 static void
4177 gtk_window_real_activate_default (GtkWindow *window)
4178 {
4179   gtk_window_activate_default (window);
4180 }
4181
4182 static void
4183 gtk_window_real_activate_focus (GtkWindow *window)
4184 {
4185   gtk_window_activate_focus (window);
4186 }
4187
4188 static void
4189 gtk_window_move_focus (GtkWindow       *window,
4190                        GtkDirectionType dir)
4191 {
4192   gtk_widget_child_focus (GTK_WIDGET (window), dir);
4193   
4194   if (!GTK_CONTAINER (window)->focus_child)
4195     gtk_window_set_focus (window, NULL);
4196 }
4197
4198 static gint
4199 gtk_window_enter_notify_event (GtkWidget        *widget,
4200                                GdkEventCrossing *event)
4201 {
4202   return FALSE;
4203 }
4204
4205 static gint
4206 gtk_window_leave_notify_event (GtkWidget        *widget,
4207                                GdkEventCrossing *event)
4208 {
4209   return FALSE;
4210 }
4211
4212 static void
4213 do_focus_change (GtkWidget *widget,
4214                  gboolean   in)
4215 {
4216   GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
4217   
4218   g_object_ref (widget);
4219   
4220   if (in)
4221     GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
4222   else
4223     GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
4224   
4225   fevent->focus_change.type = GDK_FOCUS_CHANGE;
4226   fevent->focus_change.window = widget->window;
4227   if (widget->window)
4228     g_object_ref (widget->window);
4229   fevent->focus_change.in = in;
4230   
4231   gtk_widget_event (widget, fevent);
4232   
4233   g_object_notify (G_OBJECT (widget), "has_focus");
4234
4235   g_object_unref (widget);
4236   gdk_event_free (fevent);
4237 }
4238
4239 static gint
4240 gtk_window_focus_in_event (GtkWidget     *widget,
4241                            GdkEventFocus *event)
4242 {
4243   GtkWindow *window = GTK_WINDOW (widget);
4244
4245   /* It appears spurious focus in events can occur when
4246    *  the window is hidden. So we'll just check to see if
4247    *  the window is visible before actually handling the
4248    *  event
4249    */
4250   if (GTK_WIDGET_VISIBLE (widget))
4251     {
4252       _gtk_window_set_has_toplevel_focus (window, TRUE);
4253       _gtk_window_set_is_active (window, TRUE);
4254     }
4255       
4256   return FALSE;
4257 }
4258
4259 static gint
4260 gtk_window_focus_out_event (GtkWidget     *widget,
4261                             GdkEventFocus *event)
4262 {
4263   GtkWindow *window = GTK_WINDOW (widget);
4264
4265   _gtk_window_set_has_toplevel_focus (window, FALSE);
4266   _gtk_window_set_is_active (window, FALSE);
4267
4268   return FALSE;
4269 }
4270
4271 static GdkAtom atom_rcfiles = GDK_NONE;
4272
4273 static void
4274 gtk_window_read_rcfiles (GtkWidget *widget,
4275                          GdkEventClient *event)
4276 {
4277   GList *embedded_windows;
4278
4279   embedded_windows = g_object_get_data (G_OBJECT (widget), "gtk-embedded");
4280   if (embedded_windows)
4281     {
4282       GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
4283       int i;
4284       
4285       for (i = 0; i < 5; i++)
4286         send_event->client.data.l[i] = 0;
4287       send_event->client.data_format = 32;
4288       send_event->client.message_type = atom_rcfiles;
4289       
4290       while (embedded_windows)
4291         {
4292           guint xid = GPOINTER_TO_UINT (embedded_windows->data);
4293           gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
4294           embedded_windows = embedded_windows->next;
4295         }
4296
4297       gdk_event_free (send_event);
4298     }
4299
4300   gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
4301 }
4302
4303 static gint
4304 gtk_window_client_event (GtkWidget      *widget,
4305                          GdkEventClient *event)
4306 {
4307   if (!atom_rcfiles)
4308     atom_rcfiles = gdk_atom_intern ("_GTK_READ_RCFILES", FALSE);
4309
4310   if (event->message_type == atom_rcfiles) 
4311     gtk_window_read_rcfiles (widget, event);    
4312
4313   return FALSE;
4314 }
4315
4316 static void
4317 gtk_window_check_resize (GtkContainer *container)
4318 {
4319   GtkWindow *window = GTK_WINDOW (container);
4320
4321   if (GTK_WIDGET_VISIBLE (container))
4322     gtk_window_move_resize (window);
4323 }
4324
4325 static gboolean
4326 gtk_window_focus (GtkWidget        *widget,
4327                   GtkDirectionType  direction)
4328 {
4329   GtkBin *bin;
4330   GtkWindow *window;
4331   GtkContainer *container;
4332   GtkWidget *old_focus_child;
4333   GtkWidget *parent;
4334
4335   container = GTK_CONTAINER (widget);
4336   window = GTK_WINDOW (widget);
4337   bin = GTK_BIN (widget);
4338
4339   old_focus_child = container->focus_child;
4340   
4341   /* We need a special implementation here to deal properly with wrapping
4342    * around in the tab chain without the danger of going into an
4343    * infinite loop.
4344    */
4345   if (old_focus_child)
4346     {
4347       if (gtk_widget_child_focus (old_focus_child, direction))
4348         return TRUE;
4349     }
4350
4351   if (window->focus_widget)
4352     {
4353       if (direction == GTK_DIR_LEFT ||
4354           direction == GTK_DIR_RIGHT ||
4355           direction == GTK_DIR_UP ||
4356           direction == GTK_DIR_DOWN)
4357         {
4358           return FALSE;
4359         }
4360       
4361       /* Wrapped off the end, clear the focus setting for the toplpevel */
4362       parent = window->focus_widget->parent;
4363       while (parent)
4364         {
4365           gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
4366           parent = GTK_WIDGET (parent)->parent;
4367         }
4368       
4369       gtk_window_set_focus (GTK_WINDOW (container), NULL);
4370     }
4371
4372   /* Now try to focus the first widget in the window */
4373   if (bin->child)
4374     {
4375       if (gtk_widget_child_focus (bin->child, direction))
4376         return TRUE;
4377     }
4378
4379   return FALSE;
4380 }
4381
4382 static void
4383 gtk_window_real_set_focus (GtkWindow *window,
4384                            GtkWidget *focus)
4385 {
4386   GtkWidget *old_focus = window->focus_widget;
4387   gboolean def_flags = 0;
4388
4389   if (old_focus)
4390     {
4391       g_object_ref (old_focus);
4392       g_object_freeze_notify (G_OBJECT (old_focus));
4393     }
4394   if (focus)
4395     {
4396       g_object_ref (focus);
4397       g_object_freeze_notify (G_OBJECT (focus));
4398     }
4399   
4400   if (window->default_widget)
4401     def_flags = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
4402   
4403   if (window->focus_widget)
4404     {
4405       if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4406           (window->focus_widget != window->default_widget))
4407         {
4408           GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
4409
4410           if (window->default_widget)
4411             GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
4412         }
4413
4414       window->focus_widget = NULL;
4415
4416       if (window->has_focus)
4417         do_focus_change (old_focus, FALSE);
4418
4419       g_object_notify (G_OBJECT (old_focus), "is_focus");
4420     }
4421
4422   /* The above notifications may have set a new focus widget,
4423    * if so, we don't want to override it.
4424    */
4425   if (focus && !window->focus_widget)
4426     {
4427       window->focus_widget = focus;
4428   
4429       if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
4430           (window->focus_widget != window->default_widget))
4431         {
4432           if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
4433             GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
4434
4435           if (window->default_widget)
4436             GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
4437         }
4438
4439       if (window->has_focus)
4440         do_focus_change (window->focus_widget, TRUE);
4441
4442       g_object_notify (G_OBJECT (window->focus_widget), "is_focus");
4443     }
4444
4445   /* If the default widget changed, a redraw will have been queued
4446    * on the old and new default widgets by gtk_window_set_default(), so
4447    * we only have to worry about the case where it didn't change.
4448    * We'll sometimes queue a draw twice on the new widget but that
4449    * is harmless.
4450    */
4451   if (window->default_widget &&
4452       (def_flags != GTK_WIDGET_FLAGS (window->default_widget)))
4453     gtk_widget_queue_draw (window->default_widget);
4454
4455   if (old_focus)
4456     {
4457       g_object_thaw_notify (G_OBJECT (old_focus));
4458       g_object_unref (old_focus);
4459     }
4460   if (focus)
4461     {
4462       g_object_thaw_notify (G_OBJECT (focus));
4463       g_object_unref (focus);
4464     }
4465 }
4466
4467 /**
4468  * _gtk_window_unset_focus_and_default:
4469  * @window: a #GtkWindow
4470  * @widget: a widget inside of @window
4471  * 
4472  * Checks whether the focus and default widgets of @window are
4473  * @widget or a descendent of @widget, and if so, unset them.
4474  **/
4475 void
4476 _gtk_window_unset_focus_and_default (GtkWindow *window,
4477                                      GtkWidget *widget)
4478
4479 {
4480   GtkWidget *child;
4481       
4482   if (GTK_CONTAINER (widget->parent)->focus_child == widget)
4483     {
4484       child = window->focus_widget;
4485       
4486       while (child && child != widget)
4487         child = child->parent;
4488   
4489       if (child == widget)
4490         gtk_window_set_focus (GTK_WINDOW (window), NULL);
4491     }
4492       
4493   child = window->default_widget;
4494       
4495   while (child && child != widget)
4496     child = child->parent;
4497       
4498   if (child == widget)
4499     gtk_window_set_default (window, NULL);
4500 }
4501
4502 /*********************************
4503  * Functions related to resizing *
4504  *********************************/
4505
4506 /* This function doesn't constrain to geometry hints */
4507 static void 
4508 gtk_window_compute_configure_request_size (GtkWindow *window,
4509                                            guint     *width,
4510                                            guint     *height)
4511 {
4512   GtkRequisition requisition;
4513   GtkWindowGeometryInfo *info;
4514   GtkWidget *widget;
4515
4516   /* Preconditions:
4517    *  - we've done a size request
4518    */
4519   
4520   widget = GTK_WIDGET (window);
4521
4522   info = gtk_window_get_geometry_info (window, FALSE);
4523   
4524   if (window->need_default_size)
4525     {
4526       gtk_widget_get_child_requisition (widget, &requisition);
4527
4528       /* Default to requisition */
4529       *width = requisition.width;
4530       *height = requisition.height;
4531
4532       /* If window is empty so requests 0, default to random nonzero size */
4533        if (*width == 0 && *height == 0)
4534          {
4535            *width = 200;
4536            *height = 200;
4537          }
4538
4539        /* Override requisition with default size */
4540
4541        if (info)
4542          {
4543            gint base_width = 0;
4544            gint base_height = 0;
4545            gint width_inc = 1;
4546            gint height_inc = 1;
4547            
4548            if (info->default_is_geometry &&
4549                (info->default_width > 0 || info->default_height > 0))
4550              {
4551                GdkGeometry geometry;
4552                guint flags;
4553                
4554                gtk_window_compute_hints (window, &geometry, &flags);
4555
4556                if (flags & GDK_HINT_BASE_SIZE)
4557                  {
4558                    base_width = geometry.base_width;
4559                    base_height = geometry.base_height;
4560                  }
4561                else if (flags & GDK_HINT_MIN_SIZE)
4562                  {
4563                    base_width = geometry.min_width;
4564                    base_height = geometry.min_height;
4565                  }
4566                if (flags & GDK_HINT_RESIZE_INC)
4567                  {
4568                    width_inc = geometry.width_inc;
4569                    height_inc = geometry.height_inc;
4570                  }
4571              }
4572              
4573            if (info->default_width > 0)
4574              *width = info->default_width * width_inc + base_width;
4575            
4576            if (info->default_height > 0)
4577              *height = info->default_height * height_inc + base_height;
4578          }
4579     }
4580   else
4581     {
4582       /* Default to keeping current size */
4583       *width = widget->allocation.width;
4584       *height = widget->allocation.height;
4585     }
4586
4587   /* Override any size with gtk_window_resize() values */
4588   if (info)
4589     {
4590       if (info->resize_width > 0)
4591         *width = info->resize_width;
4592
4593       if (info->resize_height > 0)
4594         *height = info->resize_height;
4595     }
4596 }
4597
4598 static GtkWindowPosition
4599 get_effective_position (GtkWindow *window)
4600 {
4601   GtkWindowPosition pos = window->position;
4602   if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
4603       (window->transient_parent == NULL ||
4604        !GTK_WIDGET_MAPPED (window->transient_parent)))
4605     pos = GTK_WIN_POS_NONE;
4606
4607   return pos;
4608 }
4609
4610 static int
4611 get_center_monitor_of_window (GtkWindow *window)
4612 {
4613   /* We could try to sort out the relative positions of the monitors and
4614    * stuff, or we could just be losers and assume you have a row
4615    * or column of monitors.
4616    */
4617   return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
4618 }
4619
4620 static int
4621 get_monitor_containing_pointer (GtkWindow *window)
4622 {
4623   gint px, py;
4624   gint monitor_num;
4625   GdkScreen *window_screen;
4626   GdkScreen *pointer_screen;
4627
4628   window_screen = gtk_window_check_screen (window);
4629   gdk_display_get_pointer (gdk_screen_get_display (window_screen),
4630                            &pointer_screen,
4631                            &px, &py, NULL);
4632
4633   if (pointer_screen == window_screen)
4634     monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
4635   else
4636     monitor_num = -1;
4637
4638   return monitor_num;
4639 }
4640
4641 static void
4642 center_window_on_monitor (GtkWindow *window,
4643                           gint       w,
4644                           gint       h,
4645                           gint      *x,
4646                           gint      *y)
4647 {
4648   GdkRectangle monitor;
4649   int monitor_num;
4650
4651   monitor_num = get_monitor_containing_pointer (window);
4652   
4653   if (monitor_num == -1)
4654     monitor_num = get_center_monitor_of_window (window);
4655
4656   gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
4657                                    monitor_num, &monitor);
4658   
4659   *x = (monitor.width - w) / 2 + monitor.x;
4660   *y = (monitor.height - h) / 2 + monitor.y;
4661
4662   /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
4663    * and WM decorations.
4664    */
4665   if (*x < monitor.x)
4666     *x = monitor.x;
4667   if (*y < monitor.y)
4668     *y = monitor.y;
4669 }
4670
4671 static void
4672 clamp_window_to_rectangle (gint               *x,
4673                            gint               *y,
4674                            gint                w,
4675                            gint                h,
4676                            const GdkRectangle *rect)
4677 {
4678   gint outside_w, outside_h;
4679   
4680   outside_w = (*x + w) - (rect->x + rect->width);
4681   if (outside_w > 0)
4682     *x -= outside_w;
4683
4684   outside_h = (*y + h) - (rect->y + rect->height);
4685   if (outside_h > 0)
4686     *y -= outside_h; 
4687
4688   /* if larger than the screen, center on the screen. */
4689   if (*x < rect->x)
4690     *x += (rect->x - *x) / 2;
4691   if (*y < rect->y)
4692     *y += (rect->y - *y) / 2;
4693 }
4694
4695
4696 static void
4697 gtk_window_compute_configure_request (GtkWindow    *window,
4698                                       GdkRectangle *request,
4699                                       GdkGeometry  *geometry,
4700                                       guint        *flags)
4701 {
4702   GdkGeometry new_geometry;
4703   guint new_flags;
4704   int w, h;
4705   GtkWidget *widget;
4706   GtkWindowPosition pos;
4707   GtkWidget *parent_widget;
4708   GtkWindowGeometryInfo *info;
4709   GdkScreen *screen;
4710   int x, y;
4711   
4712   widget = GTK_WIDGET (window);
4713
4714   screen = gtk_window_check_screen (window);
4715   
4716   gtk_widget_size_request (widget, NULL);
4717   gtk_window_compute_configure_request_size (window, &w, &h);
4718   
4719   gtk_window_compute_hints (window, &new_geometry, &new_flags);
4720   gtk_window_constrain_size (window,
4721                              &new_geometry, new_flags,
4722                              w, h,
4723                              &w, &h);
4724
4725   parent_widget = (GtkWidget*) window->transient_parent;
4726   
4727   pos = get_effective_position (window);
4728   info = gtk_window_get_geometry_info (window, TRUE);
4729
4730   /* by default, don't change position requested */
4731   x = info->last.configure_request.x;
4732   y = info->last.configure_request.y;
4733   
4734   if (window->need_default_position)
4735     {
4736
4737       /* FIXME this all interrelates with window gravity.
4738        * For most of them I think we want to set GRAVITY_CENTER.
4739        *
4740        * Not sure how to go about that.
4741        */
4742       
4743       switch (pos)
4744         {
4745           /* here we are only handling CENTER_ALWAYS
4746            * as it relates to default positioning,
4747            * where it's equivalent to simply CENTER
4748            */
4749         case GTK_WIN_POS_CENTER_ALWAYS:
4750         case GTK_WIN_POS_CENTER:
4751           center_window_on_monitor (window, w, h, &x, &y);
4752           break;
4753       
4754         case GTK_WIN_POS_CENTER_ON_PARENT:
4755           {
4756             gint monitor_num;
4757             GdkRectangle monitor;
4758             gint ox, oy;
4759             
4760             g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
4761
4762             if (parent_widget->window != NULL)
4763               monitor_num = gdk_screen_get_monitor_at_window (screen,
4764                                                               parent_widget->window);
4765             else
4766               monitor_num = -1;
4767             
4768             gdk_window_get_origin (parent_widget->window,
4769                                    &ox, &oy);
4770             
4771             x = ox + (parent_widget->allocation.width - w) / 2;
4772             y = oy + (parent_widget->allocation.height - h) / 2;
4773             
4774             /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
4775              * WM decorations. If parent wasn't on a monitor, just
4776              * give up.
4777              */
4778             if (monitor_num >= 0)
4779               {
4780                 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
4781                 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
4782               }
4783           }
4784           break;
4785
4786         case GTK_WIN_POS_MOUSE:
4787           {
4788             gint screen_width = gdk_screen_get_width (screen);
4789             gint screen_height = gdk_screen_get_height (screen);
4790             gint monitor_num;
4791             GdkRectangle monitor;
4792             GdkScreen *pointer_screen;
4793             gint px, py;
4794             
4795             gdk_display_get_pointer (gdk_screen_get_display (screen),
4796                                      &pointer_screen,
4797                                      &px, &py, NULL);
4798
4799             if (pointer_screen == screen)
4800               monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
4801             else
4802               monitor_num = -1;
4803             
4804             x = px - w / 2;
4805             y = py - h / 2;
4806             x = CLAMP (x, 0, screen_width - w);
4807             y = CLAMP (y, 0, screen_height - h);
4808
4809             /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
4810              * WM decorations. Don't try to figure out what's going
4811              * on if the mouse wasn't inside a monitor.
4812              */
4813             if (monitor_num >= 0)
4814               {
4815                 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
4816                 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
4817               }
4818           }
4819           break;
4820
4821         default:
4822           break;
4823         }
4824     } /* if (window->need_default_position) */
4825
4826   if (window->need_default_position &&
4827       info->initial_pos_set)
4828     {
4829       x = info->initial_x;
4830       y = info->initial_y;
4831       gtk_window_constrain_position (window, w, h, &x, &y);
4832     }
4833   
4834   request->x = x;
4835   request->y = y;
4836   request->width = w;
4837   request->height = h;
4838
4839   if (geometry)
4840     *geometry = new_geometry;
4841   if (flags)
4842     *flags = new_flags;
4843 }
4844
4845 static void
4846 gtk_window_constrain_position (GtkWindow    *window,
4847                                gint          new_width,
4848                                gint          new_height,
4849                                gint         *x,
4850                                gint         *y)
4851 {
4852   /* See long comments in gtk_window_move_resize()
4853    * on when it's safe to call this function.
4854    */
4855   if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
4856     {
4857       gint center_x, center_y;
4858
4859       center_window_on_monitor (window, new_width, new_height, &center_x, &center_y);
4860       
4861       *x = center_x;
4862       *y = center_y;
4863     }
4864 }
4865
4866 static void
4867 gtk_window_move_resize (GtkWindow *window)
4868 {
4869   /* Overview:
4870    *
4871    * First we determine whether any information has changed that would
4872    * cause us to revise our last configure request.  If we would send
4873    * a different configure request from last time, then
4874    * configure_request_size_changed = TRUE or
4875    * configure_request_pos_changed = TRUE. configure_request_size_changed
4876    * may be true due to new hints, a gtk_window_resize(), or whatever.
4877    * configure_request_pos_changed may be true due to gtk_window_set_position()
4878    * or gtk_window_move().
4879    *
4880    * If the configure request has changed, we send off a new one.  To
4881    * ensure GTK+ invariants are maintained (resize queue does what it
4882    * should), we go ahead and size_allocate the requested size in this
4883    * function.
4884    *
4885    * If the configure request has not changed, we don't ever resend
4886    * it, because it could mean fighting the user or window manager.
4887    *
4888    * 
4889    *   To prepare the configure request, we come up with a base size/pos:
4890    *      - the one from gtk_window_move()/gtk_window_resize()
4891    *      - else default_width, default_height if we haven't ever
4892    *        been mapped
4893    *      - else the size request if we haven't ever been mapped,
4894    *        as a substitute default size
4895    *      - else the current size of the window, as received from
4896    *        configure notifies (i.e. the current allocation)
4897    *
4898    *   If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
4899    *   the position request to be centered.
4900    */
4901   GtkWidget *widget;
4902   GtkContainer *container;
4903   GtkWindowGeometryInfo *info;
4904   GdkGeometry new_geometry;
4905   guint new_flags;
4906   GdkRectangle new_request;
4907   gboolean configure_request_size_changed;
4908   gboolean configure_request_pos_changed;
4909   gboolean hints_changed; /* do we need to send these again */
4910   GtkWindowLastGeometryInfo saved_last_info;
4911   
4912   widget = GTK_WIDGET (window);
4913   container = GTK_CONTAINER (widget);
4914   info = gtk_window_get_geometry_info (window, TRUE);
4915   
4916   configure_request_size_changed = FALSE;
4917   configure_request_pos_changed = FALSE;
4918   
4919   gtk_window_compute_configure_request (window, &new_request,
4920                                         &new_geometry, &new_flags);  
4921   
4922   /* This check implies the invariant that we never set info->last
4923    * without setting the hints and sending off a configure request.
4924    *
4925    * If we change info->last without sending the request, we may
4926    * miss a request.
4927    */
4928   if (info->last.configure_request.x != new_request.x ||
4929       info->last.configure_request.y != new_request.y)
4930     configure_request_pos_changed = TRUE;
4931
4932   if ((info->last.configure_request.width != new_request.width ||
4933        info->last.configure_request.height != new_request.height))
4934     configure_request_size_changed = TRUE;
4935   
4936   hints_changed = FALSE;
4937   
4938   if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
4939                                  &new_geometry, new_flags))
4940     {
4941       hints_changed = TRUE;
4942     }
4943   
4944   /* Position Constraints
4945    * ====================
4946    * 
4947    * POS_CENTER_ALWAYS is conceptually a constraint rather than
4948    * a default. The other POS_ values are used only when the
4949    * window is shown, not after that.
4950    * 
4951    * However, we can't implement a position constraint as
4952    * "anytime the window size changes, center the window"
4953    * because this may well end up fighting the WM or user.  In
4954    * fact it gets in an infinite loop with at least one WM.
4955    *
4956    * Basically, applications are in no way in a position to
4957    * constrain the position of a window, with one exception:
4958    * override redirect windows. (Really the intended purpose
4959    * of CENTER_ALWAYS anyhow, I would think.)
4960    *
4961    * So the way we implement this "constraint" is to say that when WE
4962    * cause a move or resize, i.e. we make a configure request changing
4963    * window size, we recompute the CENTER_ALWAYS position to reflect
4964    * the new window size, and include it in our request.  Also, if we
4965    * just turned on CENTER_ALWAYS we snap to center with a new
4966    * request.  Otherwise, if we are just NOTIFIED of a move or resize
4967    * done by someone else e.g. the window manager, we do NOT send a
4968    * new configure request.
4969    *
4970    * For override redirect windows, this works fine; all window
4971    * sizes are from our configure requests. For managed windows,
4972    * it is at least semi-sane, though who knows what the
4973    * app author is thinking.
4974    */
4975
4976   /* This condition should be kept in sync with the condition later on
4977    * that determines whether we send a configure request.  i.e. we
4978    * should do this position constraining anytime we were going to
4979    * send a configure request anyhow, plus when constraints have
4980    * changed.
4981    */
4982   if (configure_request_pos_changed ||
4983       configure_request_size_changed ||
4984       hints_changed ||
4985       info->position_constraints_changed)
4986     {
4987       /* We request the constrained position if:
4988        *  - we were changing position, and need to clamp
4989        *    the change to the constraint
4990        *  - we're changing the size anyway
4991        *  - set_position() was called to toggle CENTER_ALWAYS on
4992        */
4993
4994       gtk_window_constrain_position (window,
4995                                      new_request.width,
4996                                      new_request.height,
4997                                      &new_request.x,
4998                                      &new_request.y);
4999       
5000       /* Update whether we need to request a move */
5001       if (info->last.configure_request.x != new_request.x ||
5002           info->last.configure_request.y != new_request.y)
5003         configure_request_pos_changed = TRUE;
5004       else
5005         configure_request_pos_changed = FALSE;
5006     }
5007
5008 #if 0
5009   if (window->type == GTK_WINDOW_TOPLEVEL)
5010     {
5011       int notify_x, notify_y;
5012
5013       /* this is the position from the last configure notify */
5014       gdk_window_get_position (widget->window, &notify_x, &notify_y);
5015     
5016       g_message ("--- %s ---\n"
5017                  "last  : %d,%d\t%d x %d\n"
5018                  "this  : %d,%d\t%d x %d\n"
5019                  "alloc : %d,%d\t%d x %d\n"
5020                  "req   :      \t%d x %d\n"
5021                  "resize:      \t%d x %d\n" 
5022                  "size_changed: %d pos_changed: %d hints_changed: %d\n"
5023                  "configure_notify_received: %d\n"
5024                  "configure_request_count: %d\n"
5025                  "position_constraints_changed: %d\n",
5026                  window->title ? window->title : "(no title)",
5027                  info->last.configure_request.x,
5028                  info->last.configure_request.y,
5029                  info->last.configure_request.width,
5030                  info->last.configure_request.height,
5031                  new_request.x,
5032                  new_request.y,
5033                  new_request.width,
5034                  new_request.height,
5035                  notify_x, notify_y,
5036                  widget->allocation.width,
5037                  widget->allocation.height,
5038                  widget->requisition.width,
5039                  widget->requisition.height,
5040                  info->resize_width,
5041                  info->resize_height,
5042                  configure_request_pos_changed,
5043                  configure_request_size_changed,
5044                  hints_changed,
5045                  window->configure_notify_received,
5046                  window->configure_request_count,
5047                  info->position_constraints_changed);
5048     }
5049 #endif
5050   
5051   saved_last_info = info->last;
5052   info->last.geometry = new_geometry;
5053   info->last.flags = new_flags;
5054   info->last.configure_request = new_request;
5055   
5056   /* need to set PPosition so the WM will look at our position,
5057    * but we don't want to count PPosition coming and going as a hints
5058    * change for future iterations. So we saved info->last prior to
5059    * this.
5060    */
5061   
5062   /* Also, if the initial position was explicitly set, then we always
5063    * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
5064    * work.
5065    */
5066
5067   /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
5068    * this is an initial map
5069    */
5070   
5071   if ((configure_request_pos_changed ||
5072        info->initial_pos_set ||
5073        (window->need_default_position &&
5074         get_effective_position (window) != GTK_WIN_POS_NONE)) &&
5075       (new_flags & GDK_HINT_POS) == 0)
5076     {
5077       new_flags |= GDK_HINT_POS;
5078       hints_changed = TRUE;
5079     }
5080   
5081   /* Set hints if necessary
5082    */
5083   if (hints_changed)
5084     gdk_window_set_geometry_hints (widget->window,
5085                                    &new_geometry,
5086                                    new_flags);
5087   
5088   /* handle resizing/moving and widget tree allocation
5089    */
5090   if (window->configure_notify_received)
5091     { 
5092       GtkAllocation allocation;
5093
5094       /* If we have received a configure event since
5095        * the last time in this function, we need to
5096        * accept our new size and size_allocate child widgets.
5097        * (see gtk_window_configure_event() for more details).
5098        *
5099        * 1 or more configure notifies may have been received.
5100        * Also, configure_notify_received will only be TRUE
5101        * if all expected configure notifies have been received
5102        * (one per configure request), as an optimization.
5103        *
5104        */
5105       window->configure_notify_received = FALSE;
5106
5107       /* gtk_window_configure_event() filled in widget->allocation */
5108       allocation = widget->allocation;
5109       gtk_widget_size_allocate (widget, &allocation);
5110
5111       /* If the configure request changed, it means that
5112        * we either:
5113        *   1) coincidentally changed hints or widget properties
5114        *      impacting the configure request before getting
5115        *      a configure notify, or
5116        *   2) some broken widget is changing its size request
5117        *      during size allocation, resulting in
5118        *      a false appearance of changed configure request.
5119        *
5120        * For 1), we could just go ahead and ask for the
5121        * new size right now, but doing that for 2)
5122        * might well be fighting the user (and can even
5123        * trigger a loop). Since we really don't want to
5124        * do that, we requeue a resize in hopes that
5125        * by the time it gets handled, the child has seen
5126        * the light and is willing to go along with the
5127        * new size. (this happens for the zvt widget, since
5128        * the size_allocate() above will have stored the
5129        * requisition corresponding to the new size in the
5130        * zvt widget)
5131        *
5132        * This doesn't buy us anything for 1), but it shouldn't
5133        * hurt us too badly, since it is what would have
5134        * happened if we had gotten the configure event before
5135        * the new size had been set.
5136        */
5137
5138       if (configure_request_size_changed ||
5139           configure_request_pos_changed)
5140         {
5141           /* Don't change the recorded last info after all, because we
5142            * haven't actually updated to the new info yet - we decided
5143            * to postpone our configure request until later.
5144            */
5145           info->last = saved_last_info;
5146           
5147           gtk_widget_queue_resize (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
5148         }
5149
5150       return;                   /* Bail out, we didn't really process the move/resize */
5151     }
5152   else if ((configure_request_size_changed || hints_changed) &&
5153            (widget->allocation.width != new_request.width ||
5154             widget->allocation.height != new_request.height))
5155
5156     {
5157       /* We are in one of the following situations:
5158        * A. configure_request_size_changed
5159        *    our requisition has changed and we need a different window size,
5160        *    so we request it from the window manager.
5161        * B. !configure_request_size_changed && hints_changed
5162        *    the window manager rejects our size, but we have just changed the
5163        *    window manager hints, so there's a chance our request will
5164        *    be honoured this time, so we try again.
5165        *
5166        * However, if the new requisition is the same as the current allocation,
5167        * we don't request it again, since we won't get a ConfigureNotify back from
5168        * the window manager unless it decides to change our requisition. If
5169        * we don't get the ConfigureNotify back, the resize queue will never be run.
5170        */
5171
5172       /* Now send the configure request */
5173       if (configure_request_pos_changed)
5174         {
5175           if (window->frame)
5176             {
5177               gdk_window_move_resize (window->frame,
5178                                       new_request.x - window->frame_left,
5179                                       new_request.y - window->frame_top,
5180                                       new_request.width + window->frame_left + window->frame_right,
5181                                       new_request.height + window->frame_top + window->frame_bottom);
5182               gdk_window_resize (widget->window,
5183                                  new_request.width, new_request.height);
5184             }
5185           else
5186             gdk_window_move_resize (widget->window,
5187                                     new_request.x, new_request.y,
5188                                     new_request.width, new_request.height);
5189         }
5190       else  /* only size changed */
5191         {
5192           if (window->frame)
5193             gdk_window_resize (window->frame,
5194                                new_request.width + window->frame_left + window->frame_right,
5195                                new_request.height + window->frame_top + window->frame_bottom);
5196           gdk_window_resize (widget->window,
5197                              new_request.width, new_request.height);
5198         }
5199       
5200       /* Increment the number of have-not-yet-received-notify requests */
5201       window->configure_request_count += 1;
5202
5203       /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
5204        * configure event in response to our resizing request.
5205        * the configure event will cause a new resize with
5206        * ->configure_notify_received=TRUE.
5207        * until then, we want to
5208        * - discard expose events
5209        * - coalesce resizes for our children
5210        * - defer any window resizes until the configure event arrived
5211        * to achieve this, we queue a resize for the window, but remove its
5212        * resizing handler, so resizing will not be handled from the next
5213        * idle handler but when the configure event arrives.
5214        *
5215        * FIXME: we should also dequeue the pending redraws here, since
5216        * we handle those ourselves upon ->configure_notify_received==TRUE.
5217        */
5218       if (container->resize_mode == GTK_RESIZE_QUEUE)
5219         {
5220           gtk_widget_queue_resize (widget);
5221           _gtk_container_dequeue_resize_handler (container);
5222         }
5223     }
5224   else
5225     {
5226       /* Handle any position changes.
5227        */
5228       if (configure_request_pos_changed)
5229         {
5230           if (window->frame)
5231             {
5232               gdk_window_move (window->frame,
5233                                new_request.x - window->frame_left,
5234                                new_request.y - window->frame_top);
5235             }
5236           else
5237             gdk_window_move (widget->window,
5238                              new_request.x, new_request.y);
5239         }
5240
5241       /* And run the resize queue.
5242        */
5243       gtk_container_resize_children (container);
5244     }
5245   
5246   /* We have now processed a move/resize since the last position
5247    * constraint change, setting of the initial position, or resize.
5248    * (Not resetting these flags here can lead to infinite loops for
5249    * GTK_RESIZE_IMMEDIATE containers)
5250    */
5251   info->position_constraints_changed = FALSE;
5252   info->initial_pos_set = FALSE;
5253   info->resize_width = -1;
5254   info->resize_height = -1;
5255 }
5256
5257 /* Compare two sets of Geometry hints for equality.
5258  */
5259 static gboolean
5260 gtk_window_compare_hints (GdkGeometry *geometry_a,
5261                           guint        flags_a,
5262                           GdkGeometry *geometry_b,
5263                           guint        flags_b)
5264 {
5265   if (flags_a != flags_b)
5266     return FALSE;
5267   
5268   if ((flags_a & GDK_HINT_MIN_SIZE) &&
5269       (geometry_a->min_width != geometry_b->min_width ||
5270        geometry_a->min_height != geometry_b->min_height))
5271     return FALSE;
5272
5273   if ((flags_a & GDK_HINT_MAX_SIZE) &&
5274       (geometry_a->max_width != geometry_b->max_width ||
5275        geometry_a->max_height != geometry_b->max_height))
5276     return FALSE;
5277
5278   if ((flags_a & GDK_HINT_BASE_SIZE) &&
5279       (geometry_a->base_width != geometry_b->base_width ||
5280        geometry_a->base_height != geometry_b->base_height))
5281     return FALSE;
5282
5283   if ((flags_a & GDK_HINT_ASPECT) &&
5284       (geometry_a->min_aspect != geometry_b->min_aspect ||
5285        geometry_a->max_aspect != geometry_b->max_aspect))
5286     return FALSE;
5287
5288   if ((flags_a & GDK_HINT_RESIZE_INC) &&
5289       (geometry_a->width_inc != geometry_b->width_inc ||
5290        geometry_a->height_inc != geometry_b->height_inc))
5291     return FALSE;
5292
5293   if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
5294       geometry_a->win_gravity != geometry_b->win_gravity)
5295     return FALSE;
5296
5297   return TRUE;
5298 }
5299
5300 void
5301 _gtk_window_constrain_size (GtkWindow   *window,
5302                             gint         width,
5303                             gint         height,
5304                             gint        *new_width,
5305                             gint        *new_height)
5306 {
5307   GtkWindowGeometryInfo *info;
5308
5309   g_return_if_fail (GTK_IS_WINDOW (window));
5310
5311   info = window->geometry_info;
5312   if (info)
5313     {
5314       GdkWindowHints flags = info->last.flags;
5315       GdkGeometry *geometry = &info->last.geometry;
5316       
5317       gtk_window_constrain_size (window,
5318                                  geometry,
5319                                  flags,
5320                                  width,
5321                                  height,
5322                                  new_width,
5323                                  new_height);
5324     }
5325 }
5326
5327 static void 
5328 gtk_window_constrain_size (GtkWindow   *window,
5329                            GdkGeometry *geometry,
5330                            guint        flags,
5331                            gint         width,
5332                            gint         height,
5333                            gint        *new_width,
5334                            gint        *new_height)
5335 {
5336   gdk_window_constrain_size (geometry, flags, width, height,
5337                              new_width, new_height);
5338 }
5339
5340 /* Compute the set of geometry hints and flags for a window
5341  * based on the application set geometry, and requisiition
5342  * of the window. gtk_widget_size_request() must have been
5343  * called first.
5344  */
5345 static void
5346 gtk_window_compute_hints (GtkWindow   *window,
5347                           GdkGeometry *new_geometry,
5348                           guint       *new_flags)
5349 {
5350   GtkWidget *widget;
5351   gint extra_width = 0;
5352   gint extra_height = 0;
5353   GtkWindowGeometryInfo *geometry_info;
5354   GtkRequisition requisition;
5355
5356   widget = GTK_WIDGET (window);
5357   
5358   gtk_widget_get_child_requisition (widget, &requisition);
5359   geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
5360
5361   if (geometry_info)
5362     {
5363       *new_flags = geometry_info->mask;
5364       *new_geometry = geometry_info->geometry;
5365     }
5366   else
5367     {
5368       *new_flags = 0;
5369     }
5370   
5371   if (geometry_info && geometry_info->widget)
5372     {
5373       GtkRequisition child_requisition;
5374
5375       /* FIXME: This really isn't right. It gets the min size wrong and forces
5376        * callers to do horrible hacks like set a huge usize on the child requisition
5377        * to get the base size right. We really want to find the answers to:
5378        *
5379        *  - If the geometry widget was infinitely big, how much extra space
5380        *    would be needed for the stuff around it.
5381        *
5382        *  - If the geometry widget was infinitely small, how big would the
5383        *    window still have to be.
5384        *
5385        * Finding these answers would be a bit of a mess here. (Bug #68668)
5386        */
5387       gtk_widget_get_child_requisition (geometry_info->widget, &child_requisition);
5388       
5389       extra_width = widget->requisition.width - child_requisition.width;
5390       extra_height = widget->requisition.height - child_requisition.height;
5391     }
5392
5393   /* We don't want to set GDK_HINT_POS in here, we just set it
5394    * in gtk_window_move_resize() when we want the position
5395    * honored.
5396    */
5397   
5398   if (*new_flags & GDK_HINT_BASE_SIZE)
5399     {
5400       new_geometry->base_width += extra_width;
5401       new_geometry->base_height += extra_height;
5402     }
5403   else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
5404            (*new_flags & GDK_HINT_RESIZE_INC) &&
5405            ((extra_width != 0) || (extra_height != 0)))
5406     {
5407       *new_flags |= GDK_HINT_BASE_SIZE;
5408       
5409       new_geometry->base_width = extra_width;
5410       new_geometry->base_height = extra_height;
5411     }
5412   
5413   if (*new_flags & GDK_HINT_MIN_SIZE)
5414     {
5415       if (new_geometry->min_width < 0)
5416         new_geometry->min_width = requisition.width;
5417       else
5418         new_geometry->min_width += extra_width;
5419
5420       if (new_geometry->min_height < 0)
5421         new_geometry->min_height = requisition.height;
5422       else
5423         new_geometry->min_height += extra_height;
5424     }
5425   else if (!window->allow_shrink)
5426     {
5427       *new_flags |= GDK_HINT_MIN_SIZE;
5428       
5429       new_geometry->min_width = requisition.width;
5430       new_geometry->min_height = requisition.height;
5431     }
5432   
5433   if (*new_flags & GDK_HINT_MAX_SIZE)
5434     {
5435       if (new_geometry->max_width < 0)
5436         new_geometry->max_width = requisition.width;
5437       else
5438         new_geometry->max_width += extra_width;
5439
5440       if (new_geometry->max_height < 0)
5441         new_geometry->max_height = requisition.height;
5442       else
5443         new_geometry->max_height += extra_height;
5444     }
5445   else if (!window->allow_grow)
5446     {
5447       *new_flags |= GDK_HINT_MAX_SIZE;
5448       
5449       new_geometry->max_width = requisition.width;
5450       new_geometry->max_height = requisition.height;
5451     }
5452
5453   *new_flags |= GDK_HINT_WIN_GRAVITY;
5454   new_geometry->win_gravity = window->gravity;
5455 }
5456
5457 /***********************
5458  * Redrawing functions *
5459  ***********************/
5460
5461 static void
5462 gtk_window_paint (GtkWidget     *widget,
5463                   GdkRectangle *area)
5464 {
5465   gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL, 
5466                       GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
5467 }
5468
5469 static gint
5470 gtk_window_expose (GtkWidget      *widget,
5471                    GdkEventExpose *event)
5472 {
5473   if (!GTK_WIDGET_APP_PAINTABLE (widget))
5474     gtk_window_paint (widget, &event->area);
5475   
5476   if (GTK_WIDGET_CLASS (parent_class)->expose_event)
5477     return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
5478
5479   return FALSE;
5480 }
5481
5482 /**
5483  * gtk_window_set_has_frame:
5484  * @window: a #GtkWindow
5485  * @setting: a boolean
5486  *
5487  * (Note: this is a special-purpose function for the framebuffer port,
5488  *  that causes GTK+ to draw its own window border. For most applications,
5489  *  you want gtk_window_set_decorated() instead, which tells the window
5490  *  manager whether to draw the window border.)
5491  * 
5492  * If this function is called on a window with setting of %TRUE, before
5493  * it is realized or showed, it will have a "frame" window around
5494  * @window->window, accessible in @window->frame. Using the signal 
5495  * frame_event you can receive all events targeted at the frame.
5496  * 
5497  * This function is used by the linux-fb port to implement managed
5498  * windows, but it could concievably be used by X-programs that
5499  * want to do their own window decorations.
5500  *
5501  **/
5502 void
5503 gtk_window_set_has_frame (GtkWindow *window, 
5504                           gboolean   setting)
5505 {
5506   g_return_if_fail (GTK_IS_WINDOW (window));
5507   g_return_if_fail (!GTK_WIDGET_REALIZED (window));
5508
5509   window->has_frame = setting != FALSE;
5510 }
5511
5512 /**
5513  * gtk_window_get_has_frame:
5514  * @window: a #GtkWindow
5515  * 
5516  * Accessor for whether the window has a frame window exterior to
5517  * @window->window. Gets the value set by gtk_window_set_has_frame ().
5518  *
5519  * Return value: %TRUE if a frame has been added to the window
5520  *   via gtk_window_set_has_frame().
5521  **/
5522 gboolean
5523 gtk_window_get_has_frame (GtkWindow *window)
5524 {
5525   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5526
5527   return window->has_frame;
5528 }
5529
5530 /**
5531  * gtk_window_set_frame_dimensions:
5532  * @window: a #GtkWindow that has a frame
5533  * @left: The width of the left border
5534  * @top: The height of the top border
5535  * @right: The width of the right border
5536  * @bottom: The height of the bottom border
5537  *
5538  * (Note: this is a special-purpose function intended for the framebuffer
5539  *  port; see gtk_window_set_has_frame(). It will have no effect on the
5540  *  window border drawn by the window manager, which is the normal
5541  *  case when using the X Window system.)
5542  *
5543  * For windows with frames (see gtk_window_set_has_frame()) this function
5544  * can be used to change the size of the frame border.
5545  **/
5546 void
5547 gtk_window_set_frame_dimensions (GtkWindow *window, 
5548                                  gint       left,
5549                                  gint       top,
5550                                  gint       right,
5551                                  gint       bottom)
5552 {
5553   GtkWidget *widget;
5554
5555   g_return_if_fail (GTK_IS_WINDOW (window));
5556
5557   widget = GTK_WIDGET (window);
5558
5559   if (window->frame_left == left &&
5560       window->frame_top == top &&
5561       window->frame_right == right && 
5562       window->frame_bottom == bottom)
5563     return;
5564
5565   window->frame_left = left;
5566   window->frame_top = top;
5567   window->frame_right = right;
5568   window->frame_bottom = bottom;
5569
5570   if (GTK_WIDGET_REALIZED (widget) && window->frame)
5571     {
5572       gint width = widget->allocation.width + left + right;
5573       gint height = widget->allocation.height + top + bottom;
5574       gdk_window_resize (window->frame, width, height);
5575       gtk_decorated_window_move_resize_window (window,
5576                                                left, top,
5577                                                widget->allocation.width,
5578                                                widget->allocation.height);
5579     }
5580 }
5581
5582 /**
5583  * gtk_window_present:
5584  * @window: a #GtkWindow
5585  *
5586  * Presents a window to the user. This may mean raising the window
5587  * in the stacking order, deiconifying it, moving it to the current
5588  * desktop, and/or giving it the keyboard focus, possibly dependent
5589  * on the user's platform, window manager, and preferences.
5590  *
5591  * If @window is hidden, this function calls gtk_widget_show()
5592  * as well.
5593  * 
5594  * This function should be used when the user tries to open a window
5595  * that's already open. Say for example the preferences dialog is
5596  * currently open, and the user chooses Preferences from the menu
5597  * a second time; use gtk_window_present() to move the already-open dialog
5598  * where the user can see it.
5599  * 
5600  **/
5601 void
5602 gtk_window_present (GtkWindow *window)
5603 {
5604   GtkWidget *widget;
5605
5606   g_return_if_fail (GTK_IS_WINDOW (window));
5607
5608   widget = GTK_WIDGET (window);
5609
5610   if (GTK_WIDGET_VISIBLE (window))
5611     {
5612       g_assert (widget->window != NULL);
5613       
5614       gdk_window_show (widget->window);
5615
5616       /* note that gdk_window_focus() will also move the window to
5617        * the current desktop, for WM spec compliant window managers.
5618        */
5619       gdk_window_focus (widget->window,
5620                         gtk_get_current_event_time ());
5621     }
5622   else
5623     {
5624       gtk_widget_show (widget);
5625     }
5626 }
5627
5628 /**
5629  * gtk_window_iconify:
5630  * @window: a #GtkWindow
5631  *
5632  * Asks to iconify (i.e. minimize) the specified @window. Note that
5633  * you shouldn't assume the window is definitely iconified afterward,
5634  * because other entities (e.g. the user or <link
5635  * linkend="gtk-X11-arch">window manager</link>) could deiconify it
5636  * again, or there may not be a window manager in which case
5637  * iconification isn't possible, etc. But normally the window will end
5638  * up iconified. Just don't write code that crashes if not.
5639  *
5640  * It's permitted to call this function before showing a window,
5641  * in which case the window will be iconified before it ever appears
5642  * onscreen.
5643  *
5644  * You can track iconification via the "window_state_event" signal
5645  * on #GtkWidget.
5646  * 
5647  **/
5648 void
5649 gtk_window_iconify (GtkWindow *window)
5650 {
5651   GtkWidget *widget;
5652   GdkWindow *toplevel;
5653   
5654   g_return_if_fail (GTK_IS_WINDOW (window));
5655
5656   widget = GTK_WIDGET (window);
5657
5658   window->iconify_initially = TRUE;
5659
5660   if (window->frame)
5661     toplevel = window->frame;
5662   else
5663     toplevel = widget->window;
5664   
5665   if (toplevel != NULL)
5666     gdk_window_iconify (toplevel);
5667 }
5668
5669 /**
5670  * gtk_window_deiconify:
5671  * @window: a #GtkWindow
5672  *
5673  * Asks to deiconify (i.e. unminimize) the specified @window. Note
5674  * that you shouldn't assume the window is definitely deiconified
5675  * afterward, because other entities (e.g. the user or <link
5676  * linkend="gtk-X11-arch">window manager</link>) could iconify it
5677  * again before your code which assumes deiconification gets to run.
5678  *
5679  * You can track iconification via the "window_state_event" signal
5680  * on #GtkWidget.
5681  **/
5682 void
5683 gtk_window_deiconify (GtkWindow *window)
5684 {
5685   GtkWidget *widget;
5686   GdkWindow *toplevel;
5687   
5688   g_return_if_fail (GTK_IS_WINDOW (window));
5689
5690   widget = GTK_WIDGET (window);
5691
5692   window->iconify_initially = FALSE;
5693
5694   if (window->frame)
5695     toplevel = window->frame;
5696   else
5697     toplevel = widget->window;
5698   
5699   if (toplevel != NULL)
5700     gdk_window_deiconify (toplevel);
5701 }
5702
5703 /**
5704  * gtk_window_stick:
5705  * @window: a #GtkWindow
5706  *
5707  * Asks to stick @window, which means that it will appear on all user
5708  * desktops. Note that you shouldn't assume the window is definitely
5709  * stuck afterward, because other entities (e.g. the user or <link
5710  * linkend="gtk-X11-arch">window manager</link>) could unstick it
5711  * again, and some window managers do not support sticking
5712  * windows. But normally the window will end up stuck. Just don't
5713  * write code that crashes if not.
5714  *
5715  * It's permitted to call this function before showing a window.
5716  *
5717  * You can track stickiness via the "window_state_event" signal
5718  * on #GtkWidget.
5719  * 
5720  **/
5721 void
5722 gtk_window_stick (GtkWindow *window)
5723 {
5724   GtkWidget *widget;
5725   GdkWindow *toplevel;
5726   
5727   g_return_if_fail (GTK_IS_WINDOW (window));
5728
5729   widget = GTK_WIDGET (window);
5730
5731   window->stick_initially = TRUE;
5732
5733   if (window->frame)
5734     toplevel = window->frame;
5735   else
5736     toplevel = widget->window;
5737   
5738   if (toplevel != NULL)
5739     gdk_window_stick (toplevel);
5740 }
5741
5742 /**
5743  * gtk_window_unstick:
5744  * @window: a #GtkWindow
5745  *
5746  * Asks to unstick @window, which means that it will appear on only
5747  * one of the user's desktops. Note that you shouldn't assume the
5748  * window is definitely unstuck afterward, because other entities
5749  * (e.g. the user or <link linkend="gtk-X11-arch">window
5750  * manager</link>) could stick it again. But normally the window will
5751  * end up stuck. Just don't write code that crashes if not.
5752  *
5753  * You can track stickiness via the "window_state_event" signal
5754  * on #GtkWidget.
5755  * 
5756  **/
5757 void
5758 gtk_window_unstick (GtkWindow *window)
5759 {
5760   GtkWidget *widget;
5761   GdkWindow *toplevel;
5762   
5763   g_return_if_fail (GTK_IS_WINDOW (window));
5764
5765   widget = GTK_WIDGET (window);
5766
5767   window->stick_initially = FALSE;
5768
5769   if (window->frame)
5770     toplevel = window->frame;
5771   else
5772     toplevel = widget->window;
5773   
5774   if (toplevel != NULL)
5775     gdk_window_unstick (toplevel);
5776 }
5777
5778 /**
5779  * gtk_window_maximize:
5780  * @window: a #GtkWindow
5781  *
5782  * Asks to maximize @window, so that it becomes full-screen. Note that
5783  * you shouldn't assume the window is definitely maximized afterward,
5784  * because other entities (e.g. the user or <link
5785  * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
5786  * again, and not all window managers support maximization. But
5787  * normally the window will end up maximized. Just don't write code
5788  * that crashes if not.
5789  *
5790  * It's permitted to call this function before showing a window,
5791  * in which case the window will be maximized when it appears onscreen
5792  * initially.
5793  *
5794  * You can track maximization via the "window_state_event" signal
5795  * on #GtkWidget.
5796  * 
5797  **/
5798 void
5799 gtk_window_maximize (GtkWindow *window)
5800 {
5801   GtkWidget *widget;
5802   GdkWindow *toplevel;
5803   
5804   g_return_if_fail (GTK_IS_WINDOW (window));
5805
5806   widget = GTK_WIDGET (window);
5807
5808   window->maximize_initially = TRUE;
5809
5810   if (window->frame)
5811     toplevel = window->frame;
5812   else
5813     toplevel = widget->window;
5814   
5815   if (toplevel != NULL)
5816     gdk_window_maximize (toplevel);
5817 }
5818
5819 /**
5820  * gtk_window_unmaximize:
5821  * @window: a #GtkWindow
5822  *
5823  * Asks to unmaximize @window. Note that you shouldn't assume the
5824  * window is definitely unmaximized afterward, because other entities
5825  * (e.g. the user or <link linkend="gtk-X11-arch">window
5826  * manager</link>) could maximize it again, and not all window
5827  * managers honor requests to unmaximize. But normally the window will
5828  * end up unmaximized. Just don't write code that crashes if not.
5829  *
5830  * You can track maximization via the "window_state_event" signal
5831  * on #GtkWidget.
5832  * 
5833  **/
5834 void
5835 gtk_window_unmaximize (GtkWindow *window)
5836 {
5837   GtkWidget *widget;
5838   GdkWindow *toplevel;
5839   
5840   g_return_if_fail (GTK_IS_WINDOW (window));
5841
5842   widget = GTK_WIDGET (window);
5843
5844   window->maximize_initially = FALSE;
5845
5846   if (window->frame)
5847     toplevel = window->frame;
5848   else
5849     toplevel = widget->window;
5850   
5851   if (toplevel != NULL)
5852     gdk_window_unmaximize (toplevel);
5853 }
5854
5855 /**
5856  * gtk_window_fullscreen:
5857  * @window: a #GtkWindow
5858  *
5859  * Asks to place @window in the fullscreen state. Note that you
5860  * shouldn't assume the window is definitely full screen afterward,
5861  * because other entities (e.g. the user or <link
5862  * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
5863  * again, and not all window managers honor requests to fullscreen
5864  * windows. But normally the window will end up fullscreen. Just
5865  * don't write code that crashes if not.
5866  *
5867  * You can track the fullscreen state via the "window_state_event" signal
5868  * on #GtkWidget.
5869  * 
5870  * Since: 2.2
5871  **/
5872 void
5873 gtk_window_fullscreen (GtkWindow *window)
5874 {
5875   GtkWidget *widget;
5876   GdkWindow *toplevel;
5877   GtkWindowPrivate *priv;
5878   
5879   g_return_if_fail (GTK_IS_WINDOW (window));
5880
5881   widget = GTK_WIDGET (window);
5882   priv = GTK_WINDOW_GET_PRIVATE (window);
5883   
5884   priv->fullscreen_initially = TRUE;
5885
5886   if (window->frame)
5887     toplevel = window->frame;
5888   else
5889     toplevel = widget->window;
5890   
5891   if (toplevel != NULL)
5892     gdk_window_fullscreen (toplevel);
5893 }
5894
5895 /**
5896  * gtk_window_unfullscreen:
5897  * @window: a #GtkWindow
5898  *
5899  * Asks to toggle off the fullscreen state for @window. Note that you
5900  * shouldn't assume the window is definitely not full screen
5901  * afterward, because other entities (e.g. the user or <link
5902  * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
5903  * again, and not all window managers honor requests to unfullscreen
5904  * windows. But normally the window will end up restored to its normal
5905  * state. Just don't write code that crashes if not.
5906  *
5907  * You can track the fullscreen state via the "window_state_event" signal
5908  * on #GtkWidget.
5909  * 
5910  * Since: 2.2
5911  **/
5912 void
5913 gtk_window_unfullscreen (GtkWindow *window)
5914 {
5915   GtkWidget *widget;
5916   GdkWindow *toplevel;
5917   GtkWindowPrivate *priv;
5918   
5919   g_return_if_fail (GTK_IS_WINDOW (window));
5920
5921   widget = GTK_WIDGET (window);
5922   priv = GTK_WINDOW_GET_PRIVATE (window);
5923   
5924   priv->fullscreen_initially = FALSE;
5925
5926   if (window->frame)
5927     toplevel = window->frame;
5928   else
5929     toplevel = widget->window;
5930   
5931   if (toplevel != NULL)
5932     gdk_window_unfullscreen (toplevel);
5933 }
5934
5935 /**
5936  * gtk_window_set_keep_above:
5937  * @window: a #GtkWindow
5938  * @setting: whether to keep @window above other windows
5939  *
5940  * Asks to keep @window above, so that it stays on top. Note that
5941  * you shouldn't assume the window is definitely above afterward,
5942  * because other entities (e.g. the user or <link
5943  * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
5944  * and not all window managers support keeping windows above. But
5945  * normally the window will end kept above. Just don't write code
5946  * that crashes if not.
5947  *
5948  * It's permitted to call this function before showing a window,
5949  * in which case the window will be kept above when it appears onscreen
5950  * initially.
5951  *
5952  * You can track the above state via the "window_state_event" signal
5953  * on #GtkWidget.
5954  *
5955  * Note that, according to the <ulink 
5956  * url="http://www.freedesktop.org/standards/wm-spec.html">Extended Window Manager Hints</ulink>
5957  * specification, the above state is mainly meant for user preferences and should not be used 
5958  * by applications e.g. for drawing attention to their dialogs.
5959  *
5960  * Since: 2.4
5961  **/
5962 void
5963 gtk_window_set_keep_above (GtkWindow *window,
5964                            gboolean   setting)
5965 {
5966   GtkWidget *widget;
5967   GtkWindowPrivate *priv;
5968   GdkWindow *toplevel;
5969
5970   g_return_if_fail (GTK_IS_WINDOW (window));
5971
5972   widget = GTK_WIDGET (window);
5973   priv = GTK_WINDOW_GET_PRIVATE (window);
5974
5975   priv->above_initially = setting;
5976   if (setting)
5977     priv->below_initially = FALSE;
5978
5979   if (window->frame)
5980     toplevel = window->frame;
5981   else
5982     toplevel = widget->window;
5983
5984   if (toplevel != NULL)
5985     gdk_window_set_keep_above (toplevel, setting);
5986 }
5987
5988 /**
5989  * gtk_window_set_keep_below:
5990  * @window: a #GtkWindow
5991  * @setting: whether to keep @window below other windows
5992  *
5993  * Asks to keep @window below, so that it stays in bottom. Note that
5994  * you shouldn't assume the window is definitely below afterward,
5995  * because other entities (e.g. the user or <link
5996  * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
5997  * and not all window managers support putting windows below. But
5998  * normally the window will be kept below. Just don't write code
5999  * that crashes if not.
6000  *
6001  * It's permitted to call this function before showing a window,
6002  * in which case the window will be kept below when it appears onscreen
6003  * initially.
6004  *
6005  * You can track the below state via the "window_state_event" signal
6006  * on #GtkWidget.
6007  *
6008  * Note that, according to the <ulink 
6009  * url="http://www.freedesktop.org/standards/wm-spec.html">Extended Window Manager Hints</ulink>
6010  * specification, the above state is mainly meant for user preferences and should not be used 
6011  * by applications e.g. for drawing attention to their dialogs.
6012  *
6013  * Since: 2.4
6014  **/
6015 void
6016 gtk_window_set_keep_below (GtkWindow *window,
6017                            gboolean   setting)
6018 {
6019   GtkWidget *widget;
6020   GtkWindowPrivate *priv;
6021   GdkWindow *toplevel;
6022
6023   g_return_if_fail (GTK_IS_WINDOW (window));
6024
6025   widget = GTK_WIDGET (window);
6026   priv = GTK_WINDOW_GET_PRIVATE (window);
6027
6028   priv->below_initially = setting;
6029   if (setting)
6030     priv->above_initially = FALSE;
6031
6032   if (window->frame)
6033     toplevel = window->frame;
6034   else
6035     toplevel = widget->window;
6036
6037   if (toplevel != NULL)
6038     gdk_window_set_keep_below (toplevel, setting);
6039 }
6040
6041 /**
6042  * gtk_window_set_resizable:
6043  * @window: a #GtkWindow
6044  * @resizable: %TRUE if the user can resize this window
6045  *
6046  * Sets whether the user can resize a window. Windows are user resizable
6047  * by default.
6048  **/
6049 void
6050 gtk_window_set_resizable (GtkWindow *window,
6051                           gboolean   resizable)
6052 {
6053   g_return_if_fail (GTK_IS_WINDOW (window));
6054
6055   gtk_window_set_policy (window, FALSE, resizable, FALSE);
6056 }
6057
6058 /**
6059  * gtk_window_get_resizable:
6060  * @window: a #GtkWindow
6061  *
6062  * Gets the value set by gtk_window_set_resizable().
6063  *
6064  * Return value: %TRUE if the user can resize the window
6065  **/
6066 gboolean
6067 gtk_window_get_resizable (GtkWindow *window)
6068 {
6069   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6070
6071   /* allow_grow is most likely to indicate the semantic concept we
6072    * mean by "resizable" (and will be a reliable indicator if
6073    * set_policy() hasn't been called)
6074    */
6075   return window->allow_grow;
6076 }
6077
6078 /**
6079  * gtk_window_set_gravity:
6080  * @window: a #GtkWindow
6081  * @gravity: window gravity
6082  *
6083  * Window gravity defines the meaning of coordinates passed to
6084  * gtk_window_move(). See gtk_window_move() and #GdkGravity for
6085  * more details.
6086  *
6087  * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
6088  * typically "do what you mean."
6089  *
6090  **/
6091 void
6092 gtk_window_set_gravity (GtkWindow *window,
6093                         GdkGravity gravity)
6094 {
6095   g_return_if_fail (GTK_IS_WINDOW (window));
6096
6097   if (gravity != window->gravity)
6098     {
6099       window->gravity = gravity;
6100
6101       /* gtk_window_move_resize() will adapt gravity
6102        */
6103       gtk_widget_queue_resize (GTK_WIDGET (window));
6104
6105       g_object_notify (G_OBJECT (window), "gravity");
6106     }
6107 }
6108
6109 /**
6110  * gtk_window_get_gravity:
6111  * @window: a #GtkWindow
6112  *
6113  * Gets the value set by gtk_window_set_gravity().
6114  *
6115  * Return value: window gravity
6116  **/
6117 GdkGravity
6118 gtk_window_get_gravity (GtkWindow *window)
6119 {
6120   g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
6121
6122   return window->gravity;
6123 }
6124
6125 /**
6126  * gtk_window_begin_resize_drag:
6127  * @window: a #GtkWindow
6128  * @button: mouse button that initiated the drag
6129  * @edge: position of the resize control
6130  * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
6131  * @root_y: Y position where the user clicked to initiate the drag
6132  * @timestamp: timestamp from the click event that initiated the drag
6133  *
6134  * Starts resizing a window. This function is used if an application
6135  * has window resizing controls. When GDK can support it, the resize
6136  * will be done using the standard mechanism for the <link
6137  * linkend="gtk-X11-arch">window manager</link> or windowing
6138  * system. Otherwise, GDK will try to emulate window resizing,
6139  * potentially not all that well, depending on the windowing system.
6140  * 
6141  **/
6142 void
6143 gtk_window_begin_resize_drag  (GtkWindow    *window,
6144                                GdkWindowEdge edge,
6145                                gint          button,
6146                                gint          root_x,
6147                                gint          root_y,
6148                                guint32       timestamp)
6149 {
6150   GtkWidget *widget;
6151   GdkWindow *toplevel;
6152   
6153   g_return_if_fail (GTK_IS_WINDOW (window));
6154   g_return_if_fail (GTK_WIDGET_VISIBLE (window));
6155   
6156   widget = GTK_WIDGET (window);
6157   
6158   if (window->frame)
6159     toplevel = window->frame;
6160   else
6161     toplevel = widget->window;
6162   
6163   gdk_window_begin_resize_drag (toplevel,
6164                                 edge, button,
6165                                 root_x, root_y,
6166                                 timestamp);
6167 }
6168
6169 /**
6170  * gtk_window_get_frame_dimensions:
6171  * @window: a #GtkWindow
6172  * @left: location to store the width of the frame at the left, or %NULL
6173  * @top: location to store the height of the frame at the top, or %NULL
6174  * @right: location to store the width of the frame at the returns, or %NULL
6175  * @bottom: location to store the height of the frame at the bottom, or %NULL
6176  *
6177  * (Note: this is a special-purpose function intended for the
6178  *  framebuffer port; see gtk_window_set_has_frame(). It will not
6179  *  return the size of the window border drawn by the <link
6180  *  linkend="gtk-X11-arch">window manager</link>, which is the normal
6181  *  case when using a windowing system.  See
6182  *  gdk_window_get_frame_extents() to get the standard window border
6183  *  extents.)
6184  * 
6185  * Retrieves the dimensions of the frame window for this toplevel.
6186  * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
6187  **/
6188 void
6189 gtk_window_get_frame_dimensions (GtkWindow *window,
6190                                  gint      *left,
6191                                  gint      *top,
6192                                  gint      *right,
6193                                  gint      *bottom)
6194 {
6195   g_return_if_fail (GTK_IS_WINDOW (window));
6196
6197   if (left)
6198     *left = window->frame_left;
6199   if (top)
6200     *top = window->frame_top;
6201   if (right)
6202     *right = window->frame_right;
6203   if (bottom)
6204     *bottom = window->frame_bottom;
6205 }
6206
6207 /**
6208  * gtk_window_begin_move_drag:
6209  * @window: a #GtkWindow
6210  * @button: mouse button that initiated the drag
6211  * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
6212  * @root_y: Y position where the user clicked to initiate the drag
6213  * @timestamp: timestamp from the click event that initiated the drag
6214  *
6215  * Starts moving a window. This function is used if an application has
6216  * window movement grips. When GDK can support it, the window movement
6217  * will be done using the standard mechanism for the <link
6218  * linkend="gtk-X11-arch">window manager</link> or windowing
6219  * system. Otherwise, GDK will try to emulate window movement,
6220  * potentially not all that well, depending on the windowing system.
6221  * 
6222  **/
6223 void
6224 gtk_window_begin_move_drag  (GtkWindow *window,
6225                              gint       button,
6226                              gint       root_x,
6227                              gint       root_y,
6228                              guint32    timestamp)
6229 {
6230   GtkWidget *widget;
6231   GdkWindow *toplevel;
6232   
6233   g_return_if_fail (GTK_IS_WINDOW (window));
6234   g_return_if_fail (GTK_WIDGET_VISIBLE (window));
6235   
6236   widget = GTK_WIDGET (window);
6237   
6238   if (window->frame)
6239     toplevel = window->frame;
6240   else
6241     toplevel = widget->window;
6242   
6243   gdk_window_begin_move_drag (toplevel,
6244                               button,
6245                               root_x, root_y,
6246                               timestamp);
6247 }
6248
6249 /** 
6250  * gtk_window_set_screen:
6251  * @window: a #GtkWindow.
6252  * @screen: a #GdkScreen.
6253  *
6254  * Sets the #GdkScreen where the @window is displayed; if
6255  * the window is already mapped, it will be unmapped, and
6256  * then remapped on the new screen.
6257  *
6258  * Since: 2.2
6259  */
6260 void
6261 gtk_window_set_screen (GtkWindow *window,
6262                        GdkScreen *screen)
6263 {
6264   GtkWidget *widget;
6265   GdkScreen *previous_screen;
6266   gboolean was_mapped;
6267   
6268   g_return_if_fail (GTK_IS_WINDOW (window));
6269   g_return_if_fail (GDK_IS_SCREEN (screen));
6270
6271   if (screen == window->screen)
6272     return;
6273
6274   widget = GTK_WIDGET (window);
6275
6276   previous_screen = window->screen;
6277   was_mapped = GTK_WIDGET_MAPPED (widget);
6278
6279   if (was_mapped)
6280     gtk_widget_unmap (widget);
6281   if (GTK_WIDGET_REALIZED (widget))
6282     gtk_widget_unrealize (widget);
6283       
6284   gtk_window_free_key_hash (window);
6285   window->screen = screen;
6286   gtk_widget_reset_rc_styles (widget);
6287   if (screen != previous_screen)
6288     _gtk_widget_propagate_screen_changed (widget, previous_screen);
6289   g_object_notify (G_OBJECT (window), "screen");
6290
6291   if (was_mapped)
6292     gtk_widget_map (widget);
6293 }
6294
6295 static GdkScreen *
6296 gtk_window_check_screen (GtkWindow *window)
6297 {
6298   if (window->screen)
6299     return window->screen;
6300   else
6301     {
6302       g_warning ("Screen for GtkWindow not set; you must always set\n"
6303                  "a screen for a GtkWindow before using the window");
6304       return NULL;
6305     }
6306 }
6307
6308 /** 
6309  * gtk_window_get_screen:
6310  * @window: a #GtkWindow.
6311  *
6312  * Returns the #GdkScreen associated with @window.
6313  *
6314  * Return value: a #GdkScreen.
6315  *
6316  * Since: 2.2
6317  */
6318 GdkScreen*
6319 gtk_window_get_screen (GtkWindow *window)
6320 {
6321   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
6322    
6323   return window->screen;
6324 }
6325
6326 /**
6327  * gtk_window_is_active:
6328  * @window: a #GtkWindow
6329  * 
6330  * Returns whether the window is part of the current active toplevel.
6331  * (That is, the toplevel window receiving keystrokes.)
6332  * The return value is %TRUE if the window is active toplevel
6333  * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
6334  * You might use this function if you wanted to draw a widget
6335  * differently in an active window from a widget in an inactive window.
6336  * See gtk_window_has_toplevel_focus()
6337  * 
6338  * Return value: %TRUE if the window part of the current active window.
6339  *
6340  * Since: 2.4
6341  **/
6342 gboolean
6343 gtk_window_is_active (GtkWindow *window)
6344 {
6345   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6346
6347   return window->is_active;
6348 }
6349
6350 /**
6351  * gtk_window_has_toplevel_focus:
6352  * @window: a #GtkWindow
6353  * 
6354  * Returns whether the input focus is within this GtkWindow.
6355  * For real toplevel windows, this is identical to gtk_window_is_active(),
6356  * but for embedded windows, like #GtkPlug, the results will differ.
6357  * 
6358  * Return value: %TRUE if the the input focus is within this GtkWindow
6359  *
6360  * Since: 2.4
6361  **/
6362 gboolean
6363 gtk_window_has_toplevel_focus (GtkWindow *window)
6364 {
6365   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6366
6367   return window->has_toplevel_focus;
6368 }
6369
6370 static void
6371 gtk_window_group_class_init (GtkWindowGroupClass *klass)
6372 {
6373 }
6374
6375 GType
6376 gtk_window_group_get_type (void)
6377 {
6378   static GType window_group_type = 0;
6379
6380   if (!window_group_type)
6381     {
6382       static const GTypeInfo window_group_info =
6383       {
6384         sizeof (GtkWindowGroupClass),
6385         NULL,           /* base_init */
6386         NULL,           /* base_finalize */
6387         (GClassInitFunc) gtk_window_group_class_init,
6388         NULL,           /* class_finalize */
6389         NULL,           /* class_data */
6390         sizeof (GtkWindowGroup),
6391         16,             /* n_preallocs */
6392         (GInstanceInitFunc) NULL,
6393       };
6394
6395       window_group_type = g_type_register_static (G_TYPE_OBJECT, "GtkWindowGroup", &window_group_info, 0);
6396     }
6397
6398   return window_group_type;
6399 }
6400
6401 /**
6402  * gtk_window_group_new:
6403  * 
6404  * Creates a new #GtkWindowGroup object. Grabs added with
6405  * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
6406  * 
6407  * Return value: a new #GtkWindowGroup. 
6408  **/
6409 GtkWindowGroup *
6410 gtk_window_group_new (void)
6411 {
6412   return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
6413 }
6414
6415 static void
6416 window_group_cleanup_grabs (GtkWindowGroup *group,
6417                             GtkWindow      *window)
6418 {
6419   GSList *tmp_list;
6420   GSList *to_remove = NULL;
6421
6422   tmp_list = group->grabs;
6423   while (tmp_list)
6424     {
6425       if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
6426         to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
6427       tmp_list = tmp_list->next;
6428     }
6429
6430   while (to_remove)
6431     {
6432       gtk_grab_remove (to_remove->data);
6433       g_object_unref (to_remove->data);
6434       to_remove = g_slist_delete_link (to_remove, to_remove);
6435     }
6436 }
6437
6438 /**
6439  * gtk_window_group_add_window:
6440  * @window_group: a #GtkWindowGroup
6441  * @window: the #GtkWindow to add
6442  * 
6443  * Adds a window to a #GtkWindowGroup. 
6444  **/
6445 void
6446 gtk_window_group_add_window (GtkWindowGroup *window_group,
6447                              GtkWindow      *window)
6448 {
6449   g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
6450   g_return_if_fail (GTK_IS_WINDOW (window));
6451
6452   if (window->group != window_group)
6453     {
6454       g_object_ref (window);
6455       g_object_ref (window_group);
6456       
6457       if (window->group)
6458         gtk_window_group_remove_window (window->group, window);
6459       else
6460         window_group_cleanup_grabs (_gtk_window_get_group (NULL), window);
6461
6462       window->group = window_group;
6463
6464       g_object_unref (window);
6465     }
6466 }
6467
6468 /**
6469  * gtk_window_group_remove_window:
6470  * @window_group: a #GtkWindowGroup
6471  * @window: the #GtkWindow to remove
6472  * 
6473  * Removes a window from a #GtkWindowGroup.
6474  **/
6475 void
6476 gtk_window_group_remove_window (GtkWindowGroup *window_group,
6477                                 GtkWindow      *window)
6478 {
6479   g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
6480   g_return_if_fail (GTK_IS_WIDGET (window));
6481   g_return_if_fail (window->group == window_group);
6482
6483   g_object_ref (window);
6484
6485   window_group_cleanup_grabs (window_group, window);
6486   window->group = NULL;
6487   
6488   g_object_unref (window_group);
6489   g_object_unref (window);
6490 }
6491
6492 /* Return the group for the window or the default group
6493  */
6494 GtkWindowGroup *
6495 _gtk_window_get_group (GtkWindow *window)
6496 {
6497   if (window && window->group)
6498     return window->group;
6499   else
6500     {
6501       static GtkWindowGroup *default_group = NULL;
6502
6503       if (!default_group)
6504         default_group = gtk_window_group_new ();
6505
6506       return default_group;
6507     }
6508 }
6509
6510
6511 /*
6512   Derived from XParseGeometry() in XFree86  
6513
6514   Copyright 1985, 1986, 1987,1998  The Open Group
6515
6516   All Rights Reserved.
6517
6518   The above copyright notice and this permission notice shall be included
6519   in all copies or substantial portions of the Software.
6520
6521   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
6522   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
6523   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
6524   IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
6525   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
6526   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
6527   OTHER DEALINGS IN THE SOFTWARE.
6528
6529   Except as contained in this notice, the name of The Open Group shall
6530   not be used in advertising or otherwise to promote the sale, use or
6531   other dealings in this Software without prior written authorization
6532   from The Open Group.
6533 */
6534
6535
6536 /*
6537  *    XParseGeometry parses strings of the form
6538  *   "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
6539  *   width, height, xoffset, and yoffset are unsigned integers.
6540  *   Example:  "=80x24+300-49"
6541  *   The equal sign is optional.
6542  *   It returns a bitmask that indicates which of the four values
6543  *   were actually found in the string.  For each value found,
6544  *   the corresponding argument is updated;  for each value
6545  *   not found, the corresponding argument is left unchanged. 
6546  */
6547
6548 /* The following code is from Xlib, and is minimally modified, so we
6549  * can track any upstream changes if required.  Don't change this
6550  * code. Or if you do, put in a huge comment marking which thing
6551  * changed.
6552  */
6553
6554 static int
6555 read_int (gchar   *string,
6556           gchar  **next)
6557 {
6558   int result = 0;
6559   int sign = 1;
6560   
6561   if (*string == '+')
6562     string++;
6563   else if (*string == '-')
6564     {
6565       string++;
6566       sign = -1;
6567     }
6568
6569   for (; (*string >= '0') && (*string <= '9'); string++)
6570     {
6571       result = (result * 10) + (*string - '0');
6572     }
6573
6574   *next = string;
6575
6576   if (sign >= 0)
6577     return (result);
6578   else
6579     return (-result);
6580 }
6581
6582 /* 
6583  * Bitmask returned by XParseGeometry().  Each bit tells if the corresponding
6584  * value (x, y, width, height) was found in the parsed string.
6585  */
6586 #define NoValue         0x0000
6587 #define XValue          0x0001
6588 #define YValue          0x0002
6589 #define WidthValue      0x0004
6590 #define HeightValue     0x0008
6591 #define AllValues       0x000F
6592 #define XNegative       0x0010
6593 #define YNegative       0x0020
6594
6595 /* Try not to reformat/modify, so we can compare/sync with X sources */
6596 static int
6597 gtk_XParseGeometry (const char   *string,
6598                     int          *x,
6599                     int          *y,
6600                     unsigned int *width,   
6601                     unsigned int *height)  
6602 {
6603   int mask = NoValue;
6604   char *strind;
6605   unsigned int tempWidth, tempHeight;
6606   int tempX, tempY;
6607   char *nextCharacter;
6608
6609   /* These initializations are just to silence gcc */
6610   tempWidth = 0;
6611   tempHeight = 0;
6612   tempX = 0;
6613   tempY = 0;
6614   
6615   if ( (string == NULL) || (*string == '\0')) return(mask);
6616   if (*string == '=')
6617     string++;  /* ignore possible '=' at beg of geometry spec */
6618
6619   strind = (char *)string;
6620   if (*strind != '+' && *strind != '-' && *strind != 'x') {
6621     tempWidth = read_int(strind, &nextCharacter);
6622     if (strind == nextCharacter) 
6623       return (0);
6624     strind = nextCharacter;
6625     mask |= WidthValue;
6626   }
6627
6628   if (*strind == 'x' || *strind == 'X') {       
6629     strind++;
6630     tempHeight = read_int(strind, &nextCharacter);
6631     if (strind == nextCharacter)
6632       return (0);
6633     strind = nextCharacter;
6634     mask |= HeightValue;
6635   }
6636
6637   if ((*strind == '+') || (*strind == '-')) {
6638     if (*strind == '-') {
6639       strind++;
6640       tempX = -read_int(strind, &nextCharacter);
6641       if (strind == nextCharacter)
6642         return (0);
6643       strind = nextCharacter;
6644       mask |= XNegative;
6645
6646     }
6647     else
6648       { strind++;
6649       tempX = read_int(strind, &nextCharacter);
6650       if (strind == nextCharacter)
6651         return(0);
6652       strind = nextCharacter;
6653       }
6654     mask |= XValue;
6655     if ((*strind == '+') || (*strind == '-')) {
6656       if (*strind == '-') {
6657         strind++;
6658         tempY = -read_int(strind, &nextCharacter);
6659         if (strind == nextCharacter)
6660           return(0);
6661         strind = nextCharacter;
6662         mask |= YNegative;
6663
6664       }
6665       else
6666         {
6667           strind++;
6668           tempY = read_int(strind, &nextCharacter);
6669           if (strind == nextCharacter)
6670             return(0);
6671           strind = nextCharacter;
6672         }
6673       mask |= YValue;
6674     }
6675   }
6676         
6677   /* If strind isn't at the end of the string the it's an invalid
6678                 geometry specification. */
6679
6680   if (*strind != '\0') return (0);
6681
6682   if (mask & XValue)
6683     *x = tempX;
6684   if (mask & YValue)
6685     *y = tempY;
6686   if (mask & WidthValue)
6687     *width = tempWidth;
6688   if (mask & HeightValue)
6689     *height = tempHeight;
6690   return (mask);
6691 }
6692
6693 /**
6694  * gtk_window_parse_geometry:
6695  * @window: a #GtkWindow
6696  * @geometry: geometry string
6697  * 
6698  * Parses a standard X Window System geometry string - see the
6699  * manual page for X (type 'man X') for details on this.
6700  * gtk_window_parse_geometry() does work on all GTK+ ports
6701  * including Win32 but is primarily intended for an X environment.
6702  *
6703  * If either a size or a position can be extracted from the
6704  * geometry string, gtk_window_parse_geometry() returns %TRUE
6705  * and calls gtk_window_set_default_size() and/or gtk_window_move()
6706  * to resize/move the window.
6707  *
6708  * If gtk_window_parse_geometry() returns %TRUE, it will also
6709  * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
6710  * indicating to the window manager that the size/position of
6711  * the window was user-specified. This causes most window
6712  * managers to honor the geometry.
6713  *
6714  * Note that for gtk_window_parse_geometry() to work as expected, it has
6715  * to be called when the window has its "final" size, i.e. after calling
6716  * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
6717  * on the window.
6718  * 
6719  * <informalexample><programlisting>
6720  * int
6721  * main (int argc, char *argv[])
6722  * {
6723  *   GtkWidget *window, vbox;
6724  *   GdkGeometry size_hints;
6725  *   
6726  *   gtk_init (&amp;argc, &amp;argv);
6727  *   
6728  *   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6729  *   vbox = gtk_vbox_new (FALSE, 0);
6730  *   
6731  *   gtk_container_add (GTK_CONTAINER (window), vbox);
6732  *   fill_with_content (vbox);
6733  *   gtk_widget_show_all (vbox);
6734  *   
6735  *   size_hints = {
6736  *     100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST  
6737  *   };
6738  *   
6739  *   gtk_window_set_geometry_hints (GTK_WINDOW (window),
6740  *                                  window,
6741  *                                  &amp;size_hints,
6742  *                                  GDK_HINT_MIN_SIZE | 
6743  *                                  GDK_HINT_BASE_SIZE | 
6744  *                                  GDK_HINT_RESIZE_INC);
6745  *   
6746  *   if (argc &gt; 1)
6747  *     {
6748  *       if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
6749  *         fprintf (stderr, "Failed to parse '&percnt;s'\n", argv[1]);
6750  *     }
6751  *    
6752  *    gtk_widget_show_all (window);
6753  *    gtk_main ();
6754  *    
6755  *    return 0;
6756  * }
6757  * </programlisting></informalexample>
6758  *
6759  * Return value: %TRUE if string was parsed successfully
6760  **/
6761 gboolean
6762 gtk_window_parse_geometry (GtkWindow   *window,
6763                            const gchar *geometry)
6764 {
6765   gint result, x, y;
6766   guint w, h;
6767   GdkGravity grav;
6768   gboolean size_set, pos_set;
6769   GdkScreen *screen;
6770   
6771   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6772   g_return_val_if_fail (geometry != NULL, FALSE);
6773
6774   screen = gtk_window_check_screen (window);
6775   
6776   result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
6777
6778   if ((result & WidthValue) == 0 ||
6779       w < 0)
6780     w = -1;
6781   if ((result & HeightValue) == 0 ||
6782       h < 0)
6783     h = -1;
6784
6785   size_set = FALSE;
6786   if ((result & WidthValue) || (result & HeightValue))
6787     {
6788       gtk_window_set_default_size_internal (window, TRUE, w, TRUE, h, TRUE);
6789       size_set = TRUE;
6790     }
6791
6792   gtk_window_get_size (window, &w, &h);
6793   
6794   grav = GDK_GRAVITY_NORTH_WEST;
6795
6796   if ((result & XNegative) && (result & YNegative))
6797     grav = GDK_GRAVITY_SOUTH_EAST;
6798   else if (result & XNegative)
6799     grav = GDK_GRAVITY_NORTH_EAST;
6800   else if (result & YNegative)
6801     grav = GDK_GRAVITY_SOUTH_WEST;
6802
6803   if ((result & XValue) == 0)
6804     x = 0;
6805
6806   if ((result & YValue) == 0)
6807     y = 0;
6808
6809   if (grav == GDK_GRAVITY_SOUTH_WEST ||
6810       grav == GDK_GRAVITY_SOUTH_EAST)
6811     y = gdk_screen_get_height (screen) - h + y;
6812
6813   if (grav == GDK_GRAVITY_SOUTH_EAST ||
6814       grav == GDK_GRAVITY_NORTH_EAST)
6815     x = gdk_screen_get_width (screen) - w + x;
6816
6817   /* we don't let you put a window offscreen; maybe some people would
6818    * prefer to be able to, but it's kind of a bogus thing to do.
6819    */
6820   if (y < 0)
6821     y = 0;
6822
6823   if (x < 0)
6824     x = 0;
6825
6826   pos_set = FALSE;
6827   if ((result & XValue) || (result & YValue))
6828     {
6829       gtk_window_set_gravity (window, grav);
6830       gtk_window_move (window, x, y);
6831       pos_set = TRUE;
6832     }
6833
6834   if (size_set || pos_set)
6835     {
6836       /* Set USSize, USPosition hints */
6837       GtkWindowGeometryInfo *info;
6838
6839       info = gtk_window_get_geometry_info (window, TRUE);
6840
6841       if (pos_set)
6842         info->mask |= GDK_HINT_USER_POS;
6843       if (size_set)
6844         info->mask |= GDK_HINT_USER_SIZE;
6845     }
6846   
6847   return result != 0;
6848 }
6849
6850 static void
6851 gtk_window_mnemonic_hash_foreach (gpointer key,
6852                                   gpointer value,
6853                                   gpointer data)
6854 {
6855   struct {
6856     GtkWindow *window;
6857     GtkWindowKeysForeachFunc func;
6858     gpointer func_data;
6859   } *info = data;
6860
6861   GtkWindowMnemonic *mnemonic = value;
6862
6863   if (mnemonic->window == info->window)
6864     (*info->func) (info->window, mnemonic->keyval, info->window->mnemonic_modifier, TRUE, info->func_data);
6865 }
6866
6867 void
6868 _gtk_window_keys_foreach (GtkWindow                *window,
6869                           GtkWindowKeysForeachFunc func,
6870                           gpointer                 func_data)
6871 {
6872   GSList *groups;
6873
6874   struct {
6875     GtkWindow *window;
6876     GtkWindowKeysForeachFunc func;
6877     gpointer func_data;
6878   } info;
6879
6880   info.window = window;
6881   info.func = func;
6882   info.func_data = func_data;
6883
6884   g_hash_table_foreach (mnemonic_hash_table,
6885                         gtk_window_mnemonic_hash_foreach,
6886                         &info);
6887
6888   groups = gtk_accel_groups_from_object (G_OBJECT (window));
6889   while (groups)
6890     {
6891       GtkAccelGroup *group = groups->data;
6892       gint i;
6893
6894       for (i = 0; i < group->n_accels; i++)
6895         {
6896           GtkAccelKey *key = &group->priv_accels[i].key;
6897           
6898           if (key->accel_key)
6899             (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
6900         }
6901       
6902       groups = groups->next;
6903     }
6904 }
6905
6906 static void
6907 gtk_window_keys_changed (GtkWindow *window)
6908 {
6909   gtk_window_free_key_hash (window);
6910   gtk_window_get_key_hash (window);
6911 }
6912
6913 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
6914
6915 struct _GtkWindowKeyEntry
6916 {
6917   guint keyval;
6918   guint modifiers;
6919   gboolean is_mnemonic;
6920 };
6921
6922 static void
6923 add_to_key_hash (GtkWindow      *window,
6924                  guint           keyval,
6925                  GdkModifierType modifiers,
6926                  gboolean        is_mnemonic,
6927                  gpointer        data)
6928 {
6929   GtkKeyHash *key_hash = data;
6930
6931   GtkWindowKeyEntry *entry = g_new (GtkWindowKeyEntry, 1);
6932
6933   entry->keyval = keyval;
6934   entry->modifiers = modifiers;
6935   entry->is_mnemonic = is_mnemonic;
6936
6937   /* GtkAccelGroup stores lowercased accelerators. To deal
6938    * with this, if <Shift> was specified, uppercase.
6939    */
6940   if (modifiers & GDK_SHIFT_MASK)
6941     {
6942       if (keyval == GDK_Tab)
6943         keyval = GDK_ISO_Left_Tab;
6944       else
6945         keyval = gdk_keyval_to_upper (keyval);
6946     }
6947   
6948   _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
6949 }
6950
6951 static GtkKeyHash *
6952 gtk_window_get_key_hash (GtkWindow *window)
6953 {
6954   GdkScreen *screen = gtk_window_check_screen (window);
6955   GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6956   
6957   if (key_hash)
6958     return key_hash;
6959   
6960   key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
6961                                 (GDestroyNotify)g_free);
6962   _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
6963   g_object_set_data (G_OBJECT (window), "gtk-window-key-hash", key_hash);
6964
6965   return key_hash;
6966 }
6967
6968 static void
6969 gtk_window_free_key_hash (GtkWindow *window)
6970 {
6971   GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6972   if (key_hash)
6973     {
6974       _gtk_key_hash_free (key_hash);
6975       g_object_set_data (G_OBJECT (window), "gtk-window-key-hash", NULL);
6976     }
6977 }
6978
6979 /**
6980  * _gtk_window_activate_key:
6981  * @window: a #GtkWindow
6982  * @event: a #GdkEventKey
6983  * 
6984  * Activates mnemonics and accelerators for this #GtKWindow
6985  * 
6986  * Return value: %TRUE if a mnemonic or accelerator was found and activated.
6987  **/
6988 gboolean
6989 _gtk_window_activate_key (GtkWindow   *window,
6990                           GdkEventKey *event)
6991 {
6992   GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6993   GtkWindowKeyEntry *found_entry = NULL;
6994
6995   if (!key_hash)
6996     {
6997       gtk_window_keys_changed (window);
6998       key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
6999     }
7000   
7001   if (key_hash)
7002     {
7003       GSList *entries = _gtk_key_hash_lookup (key_hash,
7004                                               event->hardware_keycode,
7005                                               event->state,
7006                                               gtk_accelerator_get_default_mod_mask (),
7007                                               event->group);
7008       GSList *tmp_list;
7009
7010       for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
7011         {
7012           GtkWindowKeyEntry *entry = tmp_list->data;
7013           if (entry->is_mnemonic)
7014             {
7015               found_entry = entry;
7016               break;
7017             }
7018         }
7019       
7020       if (!found_entry && entries)
7021         found_entry = entries->data;
7022
7023       g_slist_free (entries);
7024     }
7025
7026   if (found_entry)
7027     {
7028       if (found_entry->is_mnemonic)
7029         return gtk_window_mnemonic_activate (window, found_entry->keyval, found_entry->modifiers);
7030       else
7031         return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval, found_entry->modifiers);
7032     }
7033   else
7034     return FALSE;
7035 }
7036
7037 static void
7038 window_update_has_focus (GtkWindow *window)
7039 {
7040   GtkWidget *widget = GTK_WIDGET (window);
7041   gboolean has_focus = window->has_toplevel_focus && window->is_active;
7042   
7043   if (has_focus != window->has_focus)
7044     {
7045       window->has_focus = has_focus;
7046       
7047       if (has_focus)
7048         {
7049           if (window->focus_widget &&
7050               window->focus_widget != widget &&
7051               !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
7052             do_focus_change (window->focus_widget, TRUE);       
7053         }
7054       else
7055         {
7056           if (window->focus_widget &&
7057               window->focus_widget != widget &&
7058               GTK_WIDGET_HAS_FOCUS (window->focus_widget))
7059             do_focus_change (window->focus_widget, FALSE);
7060         }
7061     }
7062 }
7063
7064 /**
7065  * _gtk_window_set_is_active:
7066  * @window: a #GtkWindow
7067  * @is_active: %TRUE if the window is in the currently active toplevel
7068  * 
7069  * Internal function that sets whether the #GtkWindow is part
7070  * of the currently active toplevel window (taking into account inter-process
7071  * embedding.)
7072  **/
7073 void
7074 _gtk_window_set_is_active (GtkWindow *window,
7075                            gboolean   is_active)
7076 {
7077   g_return_if_fail (GTK_IS_WINDOW (window));
7078
7079   is_active = is_active != FALSE;
7080
7081   if (is_active != window->is_active)
7082     {
7083       window->is_active = is_active;
7084       window_update_has_focus (window);
7085
7086       g_object_notify (G_OBJECT (window), "is_active");
7087     }
7088 }
7089
7090 /**
7091  * _gtk_window_set_has_toplevel_focus:
7092  * @window: a #GtkWindow
7093  * @has_toplevel_focus: %TRUE if the in
7094  * 
7095  * Internal function that sets whether the keyboard focus for the
7096  * toplevel window (taking into account inter-process embedding.)
7097  **/
7098 void
7099 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
7100                                    gboolean   has_toplevel_focus)
7101 {
7102   g_return_if_fail (GTK_IS_WINDOW (window));
7103   
7104   has_toplevel_focus = has_toplevel_focus != FALSE;
7105
7106   if (has_toplevel_focus != window->has_toplevel_focus)
7107     {
7108       window->has_toplevel_focus = has_toplevel_focus;
7109       window_update_has_focus (window);
7110
7111       g_object_notify (G_OBJECT (window), "has_toplevel_focus");
7112     }
7113 }
7114
7115 /**
7116  * gtk_window_set_auto_startup_notification:
7117  * @setting: %TRUE to automatically do startup notification
7118  *
7119  * By default, after showing the first #GtkWindow for each #GdkScreen,
7120  * GTK+ calls gdk_screen_notify_startup_complete().  Call this
7121  * function to disable the automatic startup notification. You might
7122  * do this if your first window is a splash screen, and you want to
7123  * delay notification until after your real main window has been
7124  * shown, for example.
7125  *
7126  * In that example, you would disable startup notification
7127  * temporarily, show your splash screen, then re-enable it so that
7128  * showing the main window would automatically result in notification.
7129  * 
7130  * Since: 2.2
7131  **/
7132 void
7133 gtk_window_set_auto_startup_notification (gboolean setting)
7134 {
7135   disable_startup_notification = !setting;
7136 }