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