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