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