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