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