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