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