]> Pileus Git - ~andy/gtk/blob - gtk/gtkwindow.c
Update Norwegian bokmål translation.
[~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   GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
4404   GtkMnemonicHash *mnemonic_hash;
4405
4406   g_free (window->title);
4407   g_free (window->wmclass_name);
4408   g_free (window->wmclass_class);
4409   g_free (window->wm_role);
4410
4411   mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4412   if (mnemonic_hash)
4413     _gtk_mnemonic_hash_free (mnemonic_hash);
4414
4415   if (window->geometry_info)
4416     {
4417       if (window->geometry_info->widget)
4418         g_signal_handlers_disconnect_by_func (window->geometry_info->widget,
4419                                               gtk_widget_destroyed,
4420                                               &window->geometry_info->widget);
4421       g_free (window->geometry_info);
4422     }
4423
4424   if (window->keys_changed_handler)
4425     {
4426       g_source_remove (window->keys_changed_handler);
4427       window->keys_changed_handler = 0;
4428     }
4429
4430   if (window->screen)
4431     g_signal_handlers_disconnect_by_func (window->screen,
4432                                           gtk_window_on_composited_changed, window);
4433
4434   g_free (priv->startup_id);
4435
4436   G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4437 }
4438
4439 static void
4440 gtk_window_show (GtkWidget *widget)
4441 {
4442   GtkWindow *window = GTK_WINDOW (widget);
4443   GtkContainer *container = GTK_CONTAINER (window);
4444   gboolean need_resize;
4445
4446   GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
4447   
4448   need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
4449   container->need_resize = FALSE;
4450
4451   if (need_resize)
4452     {
4453       GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4454       GtkAllocation allocation = { 0, 0 };
4455       GdkRectangle configure_request;
4456       GdkGeometry new_geometry;
4457       guint new_flags;
4458       gboolean was_realized;
4459
4460       /* We are going to go ahead and perform this configure request
4461        * and then emulate a configure notify by going ahead and
4462        * doing a size allocate. Sort of a synchronous
4463        * mini-copy of gtk_window_move_resize() here.
4464        */
4465       gtk_window_compute_configure_request (window,
4466                                             &configure_request,
4467                                             &new_geometry,
4468                                             &new_flags);
4469       
4470       /* We update this because we are going to go ahead
4471        * and gdk_window_resize() below, rather than
4472        * queuing it.
4473        */
4474       info->last.configure_request.width = configure_request.width;
4475       info->last.configure_request.height = configure_request.height;
4476       
4477       /* and allocate the window - this is normally done
4478        * in move_resize in response to configure notify
4479        */
4480       allocation.width  = configure_request.width;
4481       allocation.height = configure_request.height;
4482       gtk_widget_size_allocate (widget, &allocation);
4483
4484       /* Then we guarantee we have a realize */
4485       was_realized = FALSE;
4486       if (!GTK_WIDGET_REALIZED (widget))
4487         {
4488           gtk_widget_realize (widget);
4489           was_realized = TRUE;
4490         }
4491
4492       /* Must be done after the windows are realized,
4493        * so that the decorations can be read
4494        */
4495       gtk_decorated_window_calculate_frame_size (window);
4496
4497       /* We only send configure request if we didn't just finish
4498        * creating the window; if we just created the window
4499        * then we created it with widget->allocation anyhow.
4500        */
4501       if (!was_realized)
4502         gdk_window_move_resize (widget->window,
4503                                 configure_request.x,
4504                                 configure_request.y,
4505                                 configure_request.width,
4506                                 configure_request.height);
4507     }
4508   
4509   gtk_container_check_resize (container);
4510
4511   gtk_widget_map (widget);
4512
4513   /* Try to make sure that we have some focused widget
4514    */
4515   if (!window->focus_widget && !GTK_IS_PLUG (window))
4516     gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD);
4517   
4518   if (window->modal)
4519     gtk_grab_add (widget);
4520 }
4521
4522 static void
4523 gtk_window_hide (GtkWidget *widget)
4524 {
4525   GtkWindow *window = GTK_WINDOW (widget);
4526
4527   GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
4528   gtk_widget_unmap (widget);
4529
4530   if (window->modal)
4531     gtk_grab_remove (widget);
4532 }
4533
4534 static void
4535 gtk_window_map (GtkWidget *widget)
4536 {
4537   GtkWindow *window = GTK_WINDOW (widget);
4538   GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
4539   GdkWindow *toplevel;
4540
4541   GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
4542
4543   if (window->bin.child &&
4544       GTK_WIDGET_VISIBLE (window->bin.child) &&
4545       !GTK_WIDGET_MAPPED (window->bin.child))
4546     gtk_widget_map (window->bin.child);
4547
4548   if (window->frame)
4549     toplevel = window->frame;
4550   else
4551     toplevel = widget->window;
4552   
4553   if (window->maximize_initially)
4554     gdk_window_maximize (toplevel);
4555   else
4556     gdk_window_unmaximize (toplevel);
4557   
4558   if (window->stick_initially)
4559     gdk_window_stick (toplevel);
4560   else
4561     gdk_window_unstick (toplevel);
4562   
4563   if (window->iconify_initially)
4564     gdk_window_iconify (toplevel);
4565   else
4566     gdk_window_deiconify (toplevel);
4567
4568   if (priv->fullscreen_initially)
4569     gdk_window_fullscreen (toplevel);
4570   else
4571     gdk_window_unfullscreen (toplevel);
4572   
4573   gdk_window_set_keep_above (toplevel, priv->above_initially);
4574
4575   gdk_window_set_keep_below (toplevel, priv->below_initially);
4576
4577   /* No longer use the default settings */
4578   window->need_default_size = FALSE;
4579   window->need_default_position = FALSE;
4580   
4581   if (priv->reset_type_hint)
4582     {
4583       /* We should only reset the type hint when the application
4584        * used gtk_window_set_type_hint() to change the hint.
4585        * Some applications use X directly to change the properties;
4586        * in that case, we shouldn't overwrite what they did.
4587        */
4588       gdk_window_set_type_hint (widget->window, priv->type_hint);
4589       priv->reset_type_hint = FALSE;
4590     }
4591
4592   gdk_window_show (widget->window);
4593
4594   if (window->frame)
4595     gdk_window_show (window->frame);
4596
4597   if (!disable_startup_notification)
4598     {
4599       /* Do we have a custom startup-notification id? */
4600       if (priv->startup_id != NULL)
4601         {
4602           /* Make sure we have a "real" id */
4603           if (!startup_id_is_fake (priv->startup_id)) 
4604             gdk_notify_startup_complete_with_id (priv->startup_id);
4605
4606           g_free (priv->startup_id);
4607           priv->startup_id = NULL;
4608         }
4609       else if (!sent_startup_notification)
4610         {
4611           sent_startup_notification = TRUE;
4612           gdk_notify_startup_complete ();
4613         }
4614     }
4615 }
4616
4617 static gboolean
4618 gtk_window_map_event (GtkWidget   *widget,
4619                       GdkEventAny *event)
4620 {
4621   if (!GTK_WIDGET_MAPPED (widget))
4622     {
4623       /* we should be be unmapped, but are getting a MapEvent, this may happen
4624        * to toplevel XWindows if mapping was intercepted by a window manager
4625        * and an unmap request occoured while the MapRequestEvent was still
4626        * being handled. we work around this situaiton here by re-requesting
4627        * the window being unmapped. more details can be found in:
4628        *   http://bugzilla.gnome.org/show_bug.cgi?id=316180
4629        */
4630       gdk_window_hide (widget->window);
4631     }
4632   return FALSE;
4633 }
4634
4635 static void
4636 gtk_window_unmap (GtkWidget *widget)
4637 {
4638   GtkWindow *window = GTK_WINDOW (widget);
4639   GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (widget);
4640   GtkWindowGeometryInfo *info;    
4641   GdkWindowState state;
4642
4643   GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
4644   if (window->frame)
4645     gdk_window_withdraw (window->frame);
4646   else 
4647     gdk_window_withdraw (widget->window);
4648   
4649   window->configure_request_count = 0;
4650   window->configure_notify_received = FALSE;
4651
4652   /* on unmap, we reset the default positioning of the window,
4653    * so it's placed again, but we don't reset the default
4654    * size of the window, so it's remembered.
4655    */
4656   window->need_default_position = TRUE;
4657
4658   info = gtk_window_get_geometry_info (window, FALSE);
4659   if (info)
4660     {
4661       info->initial_pos_set = FALSE;
4662       info->position_constraints_changed = FALSE;
4663     }
4664
4665   state = gdk_window_get_state (widget->window);
4666   window->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4667   window->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4668   window->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4669   priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4670   priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4671 }
4672
4673 static void
4674 gtk_window_realize (GtkWidget *widget)
4675 {
4676   GtkWindow *window;
4677   GdkWindow *parent_window;
4678   GdkWindowAttr attributes;
4679   gint attributes_mask;
4680   GtkWindowPrivate *priv;
4681   
4682   window = GTK_WINDOW (widget);
4683   priv = GTK_WINDOW_GET_PRIVATE (window);
4684
4685   /* ensure widget tree is properly size allocated */
4686   if (widget->allocation.x == -1 &&
4687       widget->allocation.y == -1 &&
4688       widget->allocation.width == 1 &&
4689       widget->allocation.height == 1)
4690     {
4691       GtkRequisition requisition;
4692       GtkAllocation allocation = { 0, 0, 200, 200 };
4693
4694       gtk_widget_size_request (widget, &requisition);
4695       if (requisition.width || requisition.height)
4696         {
4697           /* non-empty window */
4698           allocation.width = requisition.width;
4699           allocation.height = requisition.height;
4700         }
4701       gtk_widget_size_allocate (widget, &allocation);
4702       
4703       _gtk_container_queue_resize (GTK_CONTAINER (widget));
4704
4705       g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
4706     }
4707   
4708   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
4709   
4710   switch (window->type)
4711     {
4712     case GTK_WINDOW_TOPLEVEL:
4713       attributes.window_type = GDK_WINDOW_TOPLEVEL;
4714       break;
4715     case GTK_WINDOW_POPUP:
4716       attributes.window_type = GDK_WINDOW_TEMP;
4717       break;
4718     default:
4719       g_warning (G_STRLOC": Unknown window type %d!", window->type);
4720       break;
4721     }
4722    
4723   attributes.title = window->title;
4724   attributes.wmclass_name = window->wmclass_name;
4725   attributes.wmclass_class = window->wmclass_class;
4726   attributes.wclass = GDK_INPUT_OUTPUT;
4727   attributes.visual = gtk_widget_get_visual (widget);
4728   attributes.colormap = gtk_widget_get_colormap (widget);
4729
4730   if (window->has_frame)
4731     {
4732       attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
4733       attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
4734       attributes.event_mask = (GDK_EXPOSURE_MASK |
4735                                GDK_KEY_PRESS_MASK |
4736                                GDK_ENTER_NOTIFY_MASK |
4737                                GDK_LEAVE_NOTIFY_MASK |
4738                                GDK_FOCUS_CHANGE_MASK |
4739                                GDK_STRUCTURE_MASK |
4740                                GDK_BUTTON_MOTION_MASK |
4741                                GDK_POINTER_MOTION_HINT_MASK |
4742                                GDK_BUTTON_PRESS_MASK |
4743                                GDK_BUTTON_RELEASE_MASK);
4744       
4745       attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
4746       
4747       window->frame = gdk_window_new (gtk_widget_get_root_window (widget),
4748                                       &attributes, attributes_mask);
4749                                                  
4750       if (priv->opacity_set)
4751         gdk_window_set_opacity (window->frame, priv->opacity);
4752
4753       gdk_window_set_user_data (window->frame, widget);
4754       
4755       attributes.window_type = GDK_WINDOW_CHILD;
4756       attributes.x = window->frame_left;
4757       attributes.y = window->frame_top;
4758     
4759       attributes_mask = GDK_WA_X | GDK_WA_Y;
4760
4761       parent_window = window->frame;
4762
4763       g_signal_connect (window,
4764                         "event",
4765                         G_CALLBACK (gtk_window_event),
4766                         NULL);
4767     }
4768   else
4769     {
4770       attributes_mask = 0;
4771       parent_window = gtk_widget_get_root_window (widget);
4772     }
4773   
4774   attributes.width = widget->allocation.width;
4775   attributes.height = widget->allocation.height;
4776   attributes.event_mask = gtk_widget_get_events (widget);
4777   attributes.event_mask |= (GDK_EXPOSURE_MASK |
4778                             GDK_KEY_PRESS_MASK |
4779                             GDK_KEY_RELEASE_MASK |
4780                             GDK_ENTER_NOTIFY_MASK |
4781                             GDK_LEAVE_NOTIFY_MASK |
4782                             GDK_FOCUS_CHANGE_MASK |
4783                             GDK_STRUCTURE_MASK);
4784   attributes.type_hint = priv->type_hint;
4785
4786   attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP | GDK_WA_TYPE_HINT;
4787   attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
4788   attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
4789   
4790   widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
4791
4792   if (!window->has_frame && priv->opacity_set)
4793     gdk_window_set_opacity (widget->window, priv->opacity);
4794
4795   gdk_window_enable_synchronized_configure (widget->window);
4796     
4797   gdk_window_set_user_data (widget->window, window);
4798       
4799   widget->style = gtk_style_attach (widget->style, widget->window);
4800   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
4801   if (window->frame)
4802     gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
4803
4804   /* This is a bad hack to set the window background. */
4805   gtk_window_paint (widget, NULL);
4806   
4807   if (window->transient_parent &&
4808       GTK_WIDGET_REALIZED (window->transient_parent))
4809     gdk_window_set_transient_for (widget->window,
4810                                   GTK_WIDGET (window->transient_parent)->window);
4811
4812   if (window->wm_role)
4813     gdk_window_set_role (widget->window, window->wm_role);
4814   
4815   if (!window->decorated)
4816     gdk_window_set_decorations (widget->window, 0);
4817
4818   if (!priv->deletable)
4819     gdk_window_set_functions (widget->window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
4820
4821   if (gtk_window_get_skip_pager_hint (window))
4822     gdk_window_set_skip_pager_hint (widget->window, TRUE);
4823
4824   if (gtk_window_get_skip_taskbar_hint (window))
4825     gdk_window_set_skip_taskbar_hint (widget->window, TRUE);
4826
4827   if (gtk_window_get_accept_focus (window))
4828     gdk_window_set_accept_focus (widget->window, TRUE);
4829   else
4830     gdk_window_set_accept_focus (widget->window, FALSE);
4831
4832   if (gtk_window_get_focus_on_map (window))
4833     gdk_window_set_focus_on_map (widget->window, TRUE);
4834   else
4835     gdk_window_set_focus_on_map (widget->window, FALSE);
4836   
4837   if (window->modal)
4838     gdk_window_set_modal_hint (widget->window, TRUE);
4839   else
4840     gdk_window_set_modal_hint (widget->window, FALSE);
4841     
4842   if (priv->startup_id)
4843     {
4844 #ifdef GDK_WINDOWING_X11
4845       guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
4846       if (timestamp != GDK_CURRENT_TIME)
4847         gdk_x11_window_set_user_time (widget->window, timestamp);
4848 #endif
4849       if (!startup_id_is_fake (priv->startup_id)) 
4850         gdk_window_set_startup_id (widget->window, priv->startup_id);
4851     }
4852
4853   /* Icons */
4854   gtk_window_realize_icon (window);
4855 }
4856
4857 static void
4858 gtk_window_unrealize (GtkWidget *widget)
4859 {
4860   GtkWindow *window;
4861   GtkWindowGeometryInfo *info;
4862
4863   window = GTK_WINDOW (widget);
4864
4865   /* On unrealize, we reset the size of the window such
4866    * that we will re-apply the default sizing stuff
4867    * next time we show the window.
4868    *
4869    * Default positioning is reset on unmap, instead of unrealize.
4870    */
4871   window->need_default_size = TRUE;
4872   info = gtk_window_get_geometry_info (window, FALSE);
4873   if (info)
4874     {
4875       info->resize_width = -1;
4876       info->resize_height = -1;
4877       info->last.configure_request.x = 0;
4878       info->last.configure_request.y = 0;
4879       info->last.configure_request.width = -1;
4880       info->last.configure_request.height = -1;
4881       /* be sure we reset geom hints on re-realize */
4882       info->last.flags = 0;
4883     }
4884   
4885   if (window->frame)
4886     {
4887       gdk_window_set_user_data (window->frame, NULL);
4888       gdk_window_destroy (window->frame);
4889       window->frame = NULL;
4890     }
4891
4892   /* Icons */
4893   gtk_window_unrealize_icon (window);
4894
4895   GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
4896 }
4897
4898 static void
4899 gtk_window_size_request (GtkWidget      *widget,
4900                          GtkRequisition *requisition)
4901 {
4902   GtkWindow *window;
4903   GtkBin *bin;
4904
4905   window = GTK_WINDOW (widget);
4906   bin = GTK_BIN (window);
4907   
4908   requisition->width = GTK_CONTAINER (window)->border_width * 2;
4909   requisition->height = GTK_CONTAINER (window)->border_width * 2;
4910
4911   if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
4912     {
4913       GtkRequisition child_requisition;
4914       
4915       gtk_widget_size_request (bin->child, &child_requisition);
4916
4917       requisition->width += child_requisition.width;
4918       requisition->height += child_requisition.height;
4919     }
4920 }
4921
4922 static void
4923 gtk_window_size_allocate (GtkWidget     *widget,
4924                           GtkAllocation *allocation)
4925 {
4926   GtkWindow *window;
4927   GtkAllocation child_allocation;
4928
4929   window = GTK_WINDOW (widget);
4930   widget->allocation = *allocation;
4931
4932   if (window->bin.child && GTK_WIDGET_VISIBLE (window->bin.child))
4933     {
4934       child_allocation.x = GTK_CONTAINER (window)->border_width;
4935       child_allocation.y = GTK_CONTAINER (window)->border_width;
4936       child_allocation.width =
4937         MAX (1, (gint)allocation->width - child_allocation.x * 2);
4938       child_allocation.height =
4939         MAX (1, (gint)allocation->height - child_allocation.y * 2);
4940
4941       gtk_widget_size_allocate (window->bin.child, &child_allocation);
4942     }
4943
4944   if (GTK_WIDGET_REALIZED (widget) && window->frame)
4945     {
4946       gdk_window_resize (window->frame,
4947                          allocation->width + window->frame_left + window->frame_right,
4948                          allocation->height + window->frame_top + window->frame_bottom);
4949     }
4950 }
4951
4952 static gint
4953 gtk_window_event (GtkWidget *widget, GdkEvent *event)
4954 {
4955   GtkWindow *window;
4956   gboolean return_val;
4957
4958   window = GTK_WINDOW (widget);
4959
4960   if (window->frame && (event->any.window == window->frame))
4961     {
4962       if ((event->type != GDK_KEY_PRESS) &&
4963           (event->type != GDK_KEY_RELEASE) &&
4964           (event->type != GDK_FOCUS_CHANGE))
4965         {
4966           g_signal_stop_emission_by_name (widget, "event");
4967           return_val = FALSE;
4968           g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
4969           return TRUE;
4970         }
4971       else
4972         {
4973           g_object_unref (event->any.window);
4974           event->any.window = g_object_ref (widget->window);
4975         }
4976     }
4977
4978   return FALSE;
4979 }
4980
4981 static gboolean
4982 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
4983 {
4984   GdkEventConfigure *configure_event;
4985   GdkRectangle rect;
4986
4987   switch (event->type)
4988     {
4989     case GDK_CONFIGURE:
4990       configure_event = (GdkEventConfigure *)event;
4991       
4992       /* Invalidate the decorations */
4993       rect.x = 0;
4994       rect.y = 0;
4995       rect.width = configure_event->width;
4996       rect.height = configure_event->height;
4997       
4998       gdk_window_invalidate_rect (window->frame, &rect, FALSE);
4999
5000       /* Pass on the (modified) configure event */
5001       configure_event->width -= window->frame_left + window->frame_right;
5002       configure_event->height -= window->frame_top + window->frame_bottom;
5003       return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
5004       break;
5005     default:
5006       break;
5007     }
5008   return FALSE;
5009 }
5010
5011 static gint
5012 gtk_window_configure_event (GtkWidget         *widget,
5013                             GdkEventConfigure *event)
5014 {
5015   GtkWindow *window = GTK_WINDOW (widget);
5016   gboolean expected_reply = window->configure_request_count > 0;
5017
5018   /* window->configure_request_count incremented for each 
5019    * configure request, and decremented to a min of 0 for
5020    * each configure notify.
5021    *
5022    * All it means is that we know we will get at least
5023    * window->configure_request_count more configure notifies.
5024    * We could get more configure notifies than that; some
5025    * of the configure notifies we get may be unrelated to
5026    * the configure requests. But we will get at least
5027    * window->configure_request_count notifies.
5028    */
5029
5030   if (window->configure_request_count > 0)
5031     {
5032       window->configure_request_count -= 1;
5033       gdk_window_thaw_toplevel_updates_libgtk_only (widget->window);
5034     }
5035   
5036   /* As an optimization, we avoid a resize when possible.
5037    *
5038    * The only times we can avoid a resize are:
5039    *   - we know only the position changed, not the size
5040    *   - we know we have made more requests and so will get more
5041    *     notifies and can wait to resize when we get them
5042    */
5043   
5044   if (!expected_reply &&
5045       (widget->allocation.width == event->width &&
5046        widget->allocation.height == event->height))
5047     {
5048       gdk_window_configure_finished (widget->window);
5049       return TRUE;
5050     }
5051
5052   /*
5053    * If we do need to resize, we do that by:
5054    *   - filling in widget->allocation with the new size
5055    *   - setting configure_notify_received to TRUE
5056    *     for use in gtk_window_move_resize()
5057    *   - queueing a resize, leading to invocation of
5058    *     gtk_window_move_resize() in an idle handler
5059    *
5060    */
5061   
5062   window->configure_notify_received = TRUE;
5063   
5064   widget->allocation.width = event->width;
5065   widget->allocation.height = event->height;
5066   
5067   _gtk_container_queue_resize (GTK_CONTAINER (widget));
5068   
5069   return TRUE;
5070 }
5071
5072 /* the accel_key and accel_mods fields of the key have to be setup
5073  * upon calling this function. it'll then return whether that key
5074  * is at all used as accelerator, and if so will OR in the
5075  * accel_flags member of the key.
5076  */
5077 gboolean
5078 _gtk_window_query_nonaccels (GtkWindow      *window,
5079                              guint           accel_key,
5080                              GdkModifierType accel_mods)
5081 {
5082   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5083
5084   /* movement keys are considered locked accels */
5085   if (!accel_mods)
5086     {
5087       static const guint bindings[] = {
5088         GDK_space, GDK_KP_Space, GDK_Return, GDK_ISO_Enter, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
5089         GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
5090       };
5091       guint i;
5092       
5093       for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5094         if (bindings[i] == accel_key)
5095           return TRUE;
5096     }
5097
5098   /* mnemonics are considered locked accels */
5099   if (accel_mods == window->mnemonic_modifier)
5100     {
5101       GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
5102       if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
5103         return TRUE;
5104     }
5105
5106   return FALSE;
5107 }
5108
5109 /**
5110  * gtk_window_propagate_key_event:
5111  * @window:  a #GtkWindow
5112  * @event:   a #GdkEventKey
5113  *
5114  * Propagate a key press or release event to the focus widget and
5115  * up the focus container chain until a widget handles @event.
5116  * This is normally called by the default ::key_press_event and
5117  * ::key_release_event handlers for toplevel windows,
5118  * however in some cases it may be useful to call this directly when
5119  * overriding the standard key handling for a toplevel window.
5120  *
5121  * Return value: %TRUE if a widget in the focus chain handled the event.
5122  **/
5123 gboolean
5124 gtk_window_propagate_key_event (GtkWindow        *window,
5125                                 GdkEventKey      *event)
5126 {
5127   gboolean handled = FALSE;
5128   GtkWidget *widget, *focus;
5129
5130   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5131
5132   widget = GTK_WIDGET (window);
5133   focus = window->focus_widget;
5134   if (focus)
5135     g_object_ref (focus);
5136   
5137   while (!handled &&
5138          focus && focus != widget &&
5139          gtk_widget_get_toplevel (focus) == widget)
5140     {
5141       GtkWidget *parent;
5142       
5143       if (GTK_WIDGET_IS_SENSITIVE (focus))
5144         handled = gtk_widget_event (focus, (GdkEvent*) event);
5145       
5146       parent = focus->parent;
5147       if (parent)
5148         g_object_ref (parent);
5149       
5150       g_object_unref (focus);
5151       
5152       focus = parent;
5153     }
5154   
5155   if (focus)
5156     g_object_unref (focus);
5157
5158   return handled;
5159 }
5160
5161 static gint
5162 gtk_window_key_press_event (GtkWidget   *widget,
5163                             GdkEventKey *event)
5164 {
5165   GtkWindow *window = GTK_WINDOW (widget);
5166   gboolean handled = FALSE;
5167
5168   /* handle mnemonics and accelerators */
5169   if (!handled)
5170     handled = gtk_window_activate_key (window, event);
5171
5172   /* handle focus widget key events */
5173   if (!handled)
5174     handled = gtk_window_propagate_key_event (window, event);
5175
5176   /* Chain up, invokes binding set */
5177   if (!handled)
5178     handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
5179
5180   return handled;
5181 }
5182
5183 static gint
5184 gtk_window_key_release_event (GtkWidget   *widget,
5185                               GdkEventKey *event)
5186 {
5187   GtkWindow *window = GTK_WINDOW (widget);
5188   gboolean handled = FALSE;
5189
5190   /* handle focus widget key events */
5191   if (!handled)
5192     handled = gtk_window_propagate_key_event (window, event);
5193
5194   /* Chain up, invokes binding set */
5195   if (!handled)
5196     handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
5197
5198   return handled;
5199 }
5200
5201 static void
5202 gtk_window_real_activate_default (GtkWindow *window)
5203 {
5204   gtk_window_activate_default (window);
5205 }
5206
5207 static void
5208 gtk_window_real_activate_focus (GtkWindow *window)
5209 {
5210   gtk_window_activate_focus (window);
5211 }
5212
5213 static void
5214 gtk_window_move_focus (GtkWindow       *window,
5215                        GtkDirectionType dir)
5216 {
5217   gtk_widget_child_focus (GTK_WIDGET (window), dir);
5218   
5219   if (!GTK_CONTAINER (window)->focus_child)
5220     gtk_window_set_focus (window, NULL);
5221 }
5222
5223 static gint
5224 gtk_window_enter_notify_event (GtkWidget        *widget,
5225                                GdkEventCrossing *event)
5226 {
5227   return FALSE;
5228 }
5229
5230 static gint
5231 gtk_window_leave_notify_event (GtkWidget        *widget,
5232                                GdkEventCrossing *event)
5233 {
5234   return FALSE;
5235 }
5236
5237 static void
5238 do_focus_change (GtkWidget *widget,
5239                  gboolean   in)
5240 {
5241   GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
5242   
5243   g_object_ref (widget);
5244   
5245   if (in)
5246     GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
5247   else
5248     GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
5249   
5250   fevent->focus_change.type = GDK_FOCUS_CHANGE;
5251   fevent->focus_change.window = widget->window;
5252   if (widget->window)
5253     g_object_ref (widget->window);
5254   fevent->focus_change.in = in;
5255   
5256   gtk_widget_event (widget, fevent);
5257   
5258   g_object_notify (G_OBJECT (widget), "has-focus");
5259
5260   g_object_unref (widget);
5261   gdk_event_free (fevent);
5262 }
5263
5264 static gint
5265 gtk_window_focus_in_event (GtkWidget     *widget,
5266                            GdkEventFocus *event)
5267 {
5268   GtkWindow *window = GTK_WINDOW (widget);
5269
5270   /* It appears spurious focus in events can occur when
5271    *  the window is hidden. So we'll just check to see if
5272    *  the window is visible before actually handling the
5273    *  event
5274    */
5275   if (GTK_WIDGET_VISIBLE (widget))
5276     {
5277       _gtk_window_set_has_toplevel_focus (window, TRUE);
5278       _gtk_window_set_is_active (window, TRUE);
5279     }
5280       
5281   return FALSE;
5282 }
5283
5284 static gint
5285 gtk_window_focus_out_event (GtkWidget     *widget,
5286                             GdkEventFocus *event)
5287 {
5288   GtkWindow *window = GTK_WINDOW (widget);
5289
5290   _gtk_window_set_has_toplevel_focus (window, FALSE);
5291   _gtk_window_set_is_active (window, FALSE);
5292
5293   return FALSE;
5294 }
5295
5296 static GdkAtom atom_rcfiles = GDK_NONE;
5297 static GdkAtom atom_iconthemes = GDK_NONE;
5298
5299 static void
5300 send_client_message_to_embedded_windows (GtkWidget *widget,
5301                                          GdkAtom    message_type)
5302 {
5303   GList *embedded_windows;
5304
5305   embedded_windows = g_object_get_qdata (G_OBJECT (widget), quark_gtk_embedded);
5306   if (embedded_windows)
5307     {
5308       GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
5309       int i;
5310       
5311       for (i = 0; i < 5; i++)
5312         send_event->client.data.l[i] = 0;
5313       send_event->client.data_format = 32;
5314       send_event->client.message_type = message_type;
5315       
5316       while (embedded_windows)
5317         {
5318           GdkNativeWindow xid = (GdkNativeWindow) embedded_windows->data;
5319           gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
5320           embedded_windows = embedded_windows->next;
5321         }
5322
5323       gdk_event_free (send_event);
5324     }
5325 }
5326
5327 static gint
5328 gtk_window_client_event (GtkWidget      *widget,
5329                          GdkEventClient *event)
5330 {
5331   if (!atom_rcfiles)
5332     {
5333       atom_rcfiles = gdk_atom_intern_static_string ("_GTK_READ_RCFILES");
5334       atom_iconthemes = gdk_atom_intern_static_string ("_GTK_LOAD_ICONTHEMES");
5335     }
5336
5337   if (event->message_type == atom_rcfiles) 
5338     {
5339       send_client_message_to_embedded_windows (widget, atom_rcfiles);
5340       gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
5341     }
5342
5343   if (event->message_type == atom_iconthemes) 
5344     {
5345       send_client_message_to_embedded_windows (widget, atom_iconthemes);
5346       _gtk_icon_theme_check_reload (gtk_widget_get_display (widget));    
5347     }
5348
5349   return FALSE;
5350 }
5351
5352 static void
5353 gtk_window_check_resize (GtkContainer *container)
5354 {
5355   GtkWindow *window = GTK_WINDOW (container);
5356
5357   if (GTK_WIDGET_VISIBLE (container))
5358     gtk_window_move_resize (window);
5359 }
5360
5361 static gboolean
5362 gtk_window_focus (GtkWidget        *widget,
5363                   GtkDirectionType  direction)
5364 {
5365   GtkBin *bin;
5366   GtkWindow *window;
5367   GtkContainer *container;
5368   GtkWidget *old_focus_child;
5369   GtkWidget *parent;
5370
5371   container = GTK_CONTAINER (widget);
5372   window = GTK_WINDOW (widget);
5373   bin = GTK_BIN (widget);
5374
5375   old_focus_child = container->focus_child;
5376   
5377   /* We need a special implementation here to deal properly with wrapping
5378    * around in the tab chain without the danger of going into an
5379    * infinite loop.
5380    */
5381   if (old_focus_child)
5382     {
5383       if (gtk_widget_child_focus (old_focus_child, direction))
5384         return TRUE;
5385     }
5386
5387   if (window->focus_widget)
5388     {
5389       if (direction == GTK_DIR_LEFT ||
5390           direction == GTK_DIR_RIGHT ||
5391           direction == GTK_DIR_UP ||
5392           direction == GTK_DIR_DOWN)
5393         {
5394           return FALSE;
5395         }
5396       
5397       /* Wrapped off the end, clear the focus setting for the toplpevel */
5398       parent = window->focus_widget->parent;
5399       while (parent)
5400         {
5401           gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
5402           parent = GTK_WIDGET (parent)->parent;
5403         }
5404       
5405       gtk_window_set_focus (GTK_WINDOW (container), NULL);
5406     }
5407
5408   /* Now try to focus the first widget in the window */
5409   if (bin->child)
5410     {
5411       if (gtk_widget_child_focus (bin->child, direction))
5412         return TRUE;
5413     }
5414
5415   return FALSE;
5416 }
5417
5418 static void
5419 gtk_window_real_set_focus (GtkWindow *window,
5420                            GtkWidget *focus)
5421 {
5422   GtkWidget *old_focus = window->focus_widget;
5423   gboolean had_default = FALSE;
5424   gboolean focus_had_default = FALSE;
5425   gboolean old_focus_had_default = FALSE;
5426
5427   if (old_focus)
5428     {
5429       g_object_ref (old_focus);
5430       g_object_freeze_notify (G_OBJECT (old_focus));
5431       old_focus_had_default = GTK_WIDGET_HAS_DEFAULT (old_focus);
5432     }
5433   if (focus)
5434     {
5435       g_object_ref (focus);
5436       g_object_freeze_notify (G_OBJECT (focus));
5437       focus_had_default = GTK_WIDGET_HAS_DEFAULT (focus);
5438     }
5439   
5440   if (window->default_widget)
5441     had_default = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
5442   
5443   if (window->focus_widget)
5444     {
5445       if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
5446           (window->focus_widget != window->default_widget))
5447         {
5448           GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
5449           gtk_widget_queue_draw (window->focus_widget);
5450           
5451           if (window->default_widget)
5452             GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
5453         }
5454
5455       window->focus_widget = NULL;
5456
5457       if (window->has_focus)
5458         do_focus_change (old_focus, FALSE);
5459
5460       g_object_notify (G_OBJECT (old_focus), "is-focus");
5461     }
5462
5463   /* The above notifications may have set a new focus widget,
5464    * if so, we don't want to override it.
5465    */
5466   if (focus && !window->focus_widget)
5467     {
5468       window->focus_widget = focus;
5469   
5470       if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
5471           (window->focus_widget != window->default_widget))
5472         {
5473           if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
5474             GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
5475
5476           if (window->default_widget)
5477             GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
5478         }
5479
5480       if (window->has_focus)
5481         do_focus_change (window->focus_widget, TRUE);
5482
5483       g_object_notify (G_OBJECT (window->focus_widget), "is-focus");
5484     }
5485
5486   /* If the default widget changed, a redraw will have been queued
5487    * on the old and new default widgets by gtk_window_set_default(), so
5488    * we only have to worry about the case where it didn't change.
5489    * We'll sometimes queue a draw twice on the new widget but that
5490    * is harmless.
5491    */
5492   if (window->default_widget &&
5493       (had_default != GTK_WIDGET_HAS_DEFAULT (window->default_widget)))
5494     gtk_widget_queue_draw (window->default_widget);
5495   
5496   if (old_focus)
5497     {
5498       if (old_focus_had_default != GTK_WIDGET_HAS_DEFAULT (old_focus))
5499         gtk_widget_queue_draw (old_focus);
5500         
5501       g_object_thaw_notify (G_OBJECT (old_focus));
5502       g_object_unref (old_focus);
5503     }
5504   if (focus)
5505     {
5506       if (focus_had_default != GTK_WIDGET_HAS_DEFAULT (focus))
5507         gtk_widget_queue_draw (focus);
5508
5509       g_object_thaw_notify (G_OBJECT (focus));
5510       g_object_unref (focus);
5511     }
5512 }
5513
5514 /**
5515  * _gtk_window_unset_focus_and_default:
5516  * @window: a #GtkWindow
5517  * @widget: a widget inside of @window
5518  * 
5519  * Checks whether the focus and default widgets of @window are
5520  * @widget or a descendent of @widget, and if so, unset them.
5521  **/
5522 void
5523 _gtk_window_unset_focus_and_default (GtkWindow *window,
5524                                      GtkWidget *widget)
5525
5526 {
5527   GtkWidget *child;
5528
5529   g_object_ref (window);
5530   g_object_ref (widget);
5531       
5532   if (GTK_CONTAINER (widget->parent)->focus_child == widget)
5533     {
5534       child = window->focus_widget;
5535       
5536       while (child && child != widget)
5537         child = child->parent;
5538   
5539       if (child == widget)
5540         gtk_window_set_focus (GTK_WINDOW (window), NULL);
5541     }
5542       
5543   child = window->default_widget;
5544       
5545   while (child && child != widget)
5546     child = child->parent;
5547       
5548   if (child == widget)
5549     gtk_window_set_default (window, NULL);
5550   
5551   g_object_unref (widget);
5552   g_object_unref (window);
5553 }
5554
5555 /*********************************
5556  * Functions related to resizing *
5557  *********************************/
5558
5559 /* This function doesn't constrain to geometry hints */
5560 static void 
5561 gtk_window_compute_configure_request_size (GtkWindow *window,
5562                                            guint     *width,
5563                                            guint     *height)
5564 {
5565   GtkRequisition requisition;
5566   GtkWindowGeometryInfo *info;
5567   GtkWidget *widget;
5568
5569   /* Preconditions:
5570    *  - we've done a size request
5571    */
5572   
5573   widget = GTK_WIDGET (window);
5574
5575   info = gtk_window_get_geometry_info (window, FALSE);
5576   
5577   if (window->need_default_size)
5578     {
5579       gtk_widget_get_child_requisition (widget, &requisition);
5580
5581       /* Default to requisition */
5582       *width = requisition.width;
5583       *height = requisition.height;
5584
5585       /* If window is empty so requests 0, default to random nonzero size */
5586        if (*width == 0 && *height == 0)
5587          {
5588            *width = 200;
5589            *height = 200;
5590          }
5591
5592        /* Override requisition with default size */
5593
5594        if (info)
5595          {
5596            gint base_width = 0;
5597            gint base_height = 0;
5598            gint min_width = 0;
5599            gint min_height = 0;
5600            gint width_inc = 1;
5601            gint height_inc = 1;
5602            
5603            if (info->default_is_geometry &&
5604                (info->default_width > 0 || info->default_height > 0))
5605              {
5606                GdkGeometry geometry;
5607                guint flags;
5608                
5609                gtk_window_compute_hints (window, &geometry, &flags);
5610
5611                if (flags & GDK_HINT_BASE_SIZE)
5612                  {
5613                    base_width = geometry.base_width;
5614                    base_height = geometry.base_height;
5615                  }
5616                if (flags & GDK_HINT_MIN_SIZE)
5617                  {
5618                    min_width = geometry.min_width;
5619                    min_height = geometry.min_height;
5620                  }
5621                if (flags & GDK_HINT_RESIZE_INC)
5622                  {
5623                    width_inc = geometry.width_inc;
5624                    height_inc = geometry.height_inc;
5625                  }
5626              }
5627              
5628            if (info->default_width > 0)
5629              *width = MAX (info->default_width * width_inc + base_width, min_width);
5630            
5631            if (info->default_height > 0)
5632              *height = MAX (info->default_height * height_inc + base_height, min_height);
5633          }
5634     }
5635   else
5636     {
5637       /* Default to keeping current size */
5638       *width = widget->allocation.width;
5639       *height = widget->allocation.height;
5640     }
5641
5642   /* Override any size with gtk_window_resize() values */
5643   if (info)
5644     {
5645       if (info->resize_width > 0)
5646         *width = info->resize_width;
5647
5648       if (info->resize_height > 0)
5649         *height = info->resize_height;
5650     }
5651 }
5652
5653 static GtkWindowPosition
5654 get_effective_position (GtkWindow *window)
5655 {
5656   GtkWindowPosition pos = window->position;
5657   if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
5658       (window->transient_parent == NULL ||
5659        !GTK_WIDGET_MAPPED (window->transient_parent)))
5660     pos = GTK_WIN_POS_NONE;
5661
5662   return pos;
5663 }
5664
5665 static int
5666 get_center_monitor_of_window (GtkWindow *window)
5667 {
5668   /* We could try to sort out the relative positions of the monitors and
5669    * stuff, or we could just be losers and assume you have a row
5670    * or column of monitors.
5671    */
5672   return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
5673 }
5674
5675 static int
5676 get_monitor_containing_pointer (GtkWindow *window)
5677 {
5678   gint px, py;
5679   gint monitor_num;
5680   GdkScreen *window_screen;
5681   GdkScreen *pointer_screen;
5682
5683   window_screen = gtk_window_check_screen (window);
5684   gdk_display_get_pointer (gdk_screen_get_display (window_screen),
5685                            &pointer_screen,
5686                            &px, &py, NULL);
5687
5688   if (pointer_screen == window_screen)
5689     monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
5690   else
5691     monitor_num = -1;
5692
5693   return monitor_num;
5694 }
5695
5696 static void
5697 center_window_on_monitor (GtkWindow *window,
5698                           gint       w,
5699                           gint       h,
5700                           gint      *x,
5701                           gint      *y)
5702 {
5703   GdkRectangle monitor;
5704   int monitor_num;
5705
5706   monitor_num = get_monitor_containing_pointer (window);
5707   
5708   if (monitor_num == -1)
5709     monitor_num = get_center_monitor_of_window (window);
5710
5711   gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
5712                                    monitor_num, &monitor);
5713   
5714   *x = (monitor.width - w) / 2 + monitor.x;
5715   *y = (monitor.height - h) / 2 + monitor.y;
5716
5717   /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
5718    * and WM decorations.
5719    */
5720   if (*x < monitor.x)
5721     *x = monitor.x;
5722   if (*y < monitor.y)
5723     *y = monitor.y;
5724 }
5725
5726 static void
5727 clamp (gint *base,
5728        gint  extent,
5729        gint  clamp_base,
5730        gint  clamp_extent)
5731 {
5732   if (extent > clamp_extent)
5733     /* Center */
5734     *base = clamp_base + clamp_extent/2 - extent/2;
5735   else if (*base < clamp_base)
5736     *base = clamp_base;
5737   else if (*base + extent > clamp_base + clamp_extent)
5738     *base = clamp_base + clamp_extent - extent;
5739 }
5740
5741 static void
5742 clamp_window_to_rectangle (gint               *x,
5743                            gint               *y,
5744                            gint                w,
5745                            gint                h,
5746                            const GdkRectangle *rect)
5747 {
5748 #ifdef DEBUGGING_OUTPUT
5749   g_print ("%s: %+d%+d %dx%d: %+d%+d: %dx%d", __FUNCTION__, rect->x, rect->y, rect->width, rect->height, *x, *y, w, h);
5750 #endif
5751
5752   /* If it is too large, center it. If it fits on the monitor but is
5753    * partially outside, move it to the closest edge. Do this
5754    * separately in x and y directions.
5755    */
5756   clamp (x, w, rect->x, rect->width);
5757   clamp (y, h, rect->y, rect->height);
5758 #ifdef DEBUGGING_OUTPUT
5759   g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
5760 #endif
5761 }
5762
5763
5764 static void
5765 gtk_window_compute_configure_request (GtkWindow    *window,
5766                                       GdkRectangle *request,
5767                                       GdkGeometry  *geometry,
5768                                       guint        *flags)
5769 {
5770   GdkGeometry new_geometry;
5771   guint new_flags;
5772   int w, h;
5773   GtkWidget *widget;
5774   GtkWindowPosition pos;
5775   GtkWidget *parent_widget;
5776   GtkWindowGeometryInfo *info;
5777   GdkScreen *screen;
5778   int x, y;
5779   
5780   widget = GTK_WIDGET (window);
5781
5782   screen = gtk_window_check_screen (window);
5783   
5784   gtk_widget_size_request (widget, NULL);
5785   gtk_window_compute_configure_request_size (window, (guint *)&w, (guint *)&h);
5786   
5787   gtk_window_compute_hints (window, &new_geometry, &new_flags);
5788   gtk_window_constrain_size (window,
5789                              &new_geometry, new_flags,
5790                              w, h,
5791                              &w, &h);
5792
5793   parent_widget = (GtkWidget*) window->transient_parent;
5794   
5795   pos = get_effective_position (window);
5796   info = gtk_window_get_geometry_info (window, FALSE);
5797   
5798   /* by default, don't change position requested */
5799   if (info)
5800     {
5801       x = info->last.configure_request.x;
5802       y = info->last.configure_request.y;
5803     }
5804   else
5805     {
5806       x = 0;
5807       y = 0;
5808     }
5809
5810
5811   if (window->need_default_position)
5812     {
5813
5814       /* FIXME this all interrelates with window gravity.
5815        * For most of them I think we want to set GRAVITY_CENTER.
5816        *
5817        * Not sure how to go about that.
5818        */
5819       
5820       switch (pos)
5821         {
5822           /* here we are only handling CENTER_ALWAYS
5823            * as it relates to default positioning,
5824            * where it's equivalent to simply CENTER
5825            */
5826         case GTK_WIN_POS_CENTER_ALWAYS:
5827         case GTK_WIN_POS_CENTER:
5828           center_window_on_monitor (window, w, h, &x, &y);
5829           break;
5830       
5831         case GTK_WIN_POS_CENTER_ON_PARENT:
5832           {
5833             gint monitor_num;
5834             GdkRectangle monitor;
5835             gint ox, oy;
5836             
5837             g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
5838
5839             if (parent_widget->window != NULL)
5840               monitor_num = gdk_screen_get_monitor_at_window (screen,
5841                                                               parent_widget->window);
5842             else
5843               monitor_num = -1;
5844             
5845             gdk_window_get_origin (parent_widget->window,
5846                                    &ox, &oy);
5847             
5848             x = ox + (parent_widget->allocation.width - w) / 2;
5849             y = oy + (parent_widget->allocation.height - h) / 2;
5850             
5851             /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
5852              * WM decorations. If parent wasn't on a monitor, just
5853              * give up.
5854              */
5855             if (monitor_num >= 0)
5856               {
5857                 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
5858                 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
5859               }
5860           }
5861           break;
5862
5863         case GTK_WIN_POS_MOUSE:
5864           {
5865             gint screen_width = gdk_screen_get_width (screen);
5866             gint screen_height = gdk_screen_get_height (screen);
5867             gint monitor_num;
5868             GdkRectangle monitor;
5869             GdkScreen *pointer_screen;
5870             gint px, py;
5871             
5872             gdk_display_get_pointer (gdk_screen_get_display (screen),
5873                                      &pointer_screen,
5874                                      &px, &py, NULL);
5875
5876             if (pointer_screen == screen)
5877               monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
5878             else
5879               monitor_num = -1;
5880             
5881             x = px - w / 2;
5882             y = py - h / 2;
5883             x = CLAMP (x, 0, screen_width - w);
5884             y = CLAMP (y, 0, screen_height - h);
5885
5886             /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
5887              * WM decorations. Don't try to figure out what's going
5888              * on if the mouse wasn't inside a monitor.
5889              */
5890             if (monitor_num >= 0)
5891               {
5892                 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
5893                 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
5894               }
5895           }
5896           break;
5897
5898         default:
5899           break;
5900         }
5901     } /* if (window->need_default_position) */
5902
5903   if (window->need_default_position && info &&
5904       info->initial_pos_set)
5905     {
5906       x = info->initial_x;
5907       y = info->initial_y;
5908       gtk_window_constrain_position (window, w, h, &x, &y);
5909     }
5910   
5911   request->x = x;
5912   request->y = y;
5913   request->width = w;
5914   request->height = h;
5915
5916   if (geometry)
5917     *geometry = new_geometry;
5918   if (flags)
5919     *flags = new_flags;
5920 }
5921
5922 static void
5923 gtk_window_constrain_position (GtkWindow    *window,
5924                                gint          new_width,
5925                                gint          new_height,
5926                                gint         *x,
5927                                gint         *y)
5928 {
5929   /* See long comments in gtk_window_move_resize()
5930    * on when it's safe to call this function.
5931    */
5932   if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
5933     {
5934       gint center_x, center_y;
5935
5936       center_window_on_monitor (window, new_width, new_height, &center_x, &center_y);
5937       
5938       *x = center_x;
5939       *y = center_y;
5940     }
5941 }
5942
5943 static void
5944 gtk_window_move_resize (GtkWindow *window)
5945 {
5946   /* Overview:
5947    *
5948    * First we determine whether any information has changed that would
5949    * cause us to revise our last configure request.  If we would send
5950    * a different configure request from last time, then
5951    * configure_request_size_changed = TRUE or
5952    * configure_request_pos_changed = TRUE. configure_request_size_changed
5953    * may be true due to new hints, a gtk_window_resize(), or whatever.
5954    * configure_request_pos_changed may be true due to gtk_window_set_position()
5955    * or gtk_window_move().
5956    *
5957    * If the configure request has changed, we send off a new one.  To
5958    * ensure GTK+ invariants are maintained (resize queue does what it
5959    * should), we go ahead and size_allocate the requested size in this
5960    * function.
5961    *
5962    * If the configure request has not changed, we don't ever resend
5963    * it, because it could mean fighting the user or window manager.
5964    *
5965    * 
5966    *   To prepare the configure request, we come up with a base size/pos:
5967    *      - the one from gtk_window_move()/gtk_window_resize()
5968    *      - else default_width, default_height if we haven't ever
5969    *        been mapped
5970    *      - else the size request if we haven't ever been mapped,
5971    *        as a substitute default size
5972    *      - else the current size of the window, as received from
5973    *        configure notifies (i.e. the current allocation)
5974    *
5975    *   If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
5976    *   the position request to be centered.
5977    */
5978   GtkWidget *widget;
5979   GtkContainer *container;
5980   GtkWindowGeometryInfo *info;
5981   GdkGeometry new_geometry;
5982   guint new_flags;
5983   GdkRectangle new_request;
5984   gboolean configure_request_size_changed;
5985   gboolean configure_request_pos_changed;
5986   gboolean hints_changed; /* do we need to send these again */
5987   GtkWindowLastGeometryInfo saved_last_info;
5988   
5989   widget = GTK_WIDGET (window);
5990   container = GTK_CONTAINER (widget);
5991   info = gtk_window_get_geometry_info (window, TRUE);
5992   
5993   configure_request_size_changed = FALSE;
5994   configure_request_pos_changed = FALSE;
5995   
5996   gtk_window_compute_configure_request (window, &new_request,
5997                                         &new_geometry, &new_flags);  
5998   
5999   /* This check implies the invariant that we never set info->last
6000    * without setting the hints and sending off a configure request.
6001    *
6002    * If we change info->last without sending the request, we may
6003    * miss a request.
6004    */
6005   if (info->last.configure_request.x != new_request.x ||
6006       info->last.configure_request.y != new_request.y)
6007     configure_request_pos_changed = TRUE;
6008
6009   if ((info->last.configure_request.width != new_request.width ||
6010        info->last.configure_request.height != new_request.height))
6011     configure_request_size_changed = TRUE;
6012   
6013   hints_changed = FALSE;
6014   
6015   if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
6016                                  &new_geometry, new_flags))
6017     {
6018       hints_changed = TRUE;
6019     }
6020   
6021   /* Position Constraints
6022    * ====================
6023    * 
6024    * POS_CENTER_ALWAYS is conceptually a constraint rather than
6025    * a default. The other POS_ values are used only when the
6026    * window is shown, not after that.
6027    * 
6028    * However, we can't implement a position constraint as
6029    * "anytime the window size changes, center the window"
6030    * because this may well end up fighting the WM or user.  In
6031    * fact it gets in an infinite loop with at least one WM.
6032    *
6033    * Basically, applications are in no way in a position to
6034    * constrain the position of a window, with one exception:
6035    * override redirect windows. (Really the intended purpose
6036    * of CENTER_ALWAYS anyhow, I would think.)
6037    *
6038    * So the way we implement this "constraint" is to say that when WE
6039    * cause a move or resize, i.e. we make a configure request changing
6040    * window size, we recompute the CENTER_ALWAYS position to reflect
6041    * the new window size, and include it in our request.  Also, if we
6042    * just turned on CENTER_ALWAYS we snap to center with a new
6043    * request.  Otherwise, if we are just NOTIFIED of a move or resize
6044    * done by someone else e.g. the window manager, we do NOT send a
6045    * new configure request.
6046    *
6047    * For override redirect windows, this works fine; all window
6048    * sizes are from our configure requests. For managed windows,
6049    * it is at least semi-sane, though who knows what the
6050    * app author is thinking.
6051    */
6052
6053   /* This condition should be kept in sync with the condition later on
6054    * that determines whether we send a configure request.  i.e. we
6055    * should do this position constraining anytime we were going to
6056    * send a configure request anyhow, plus when constraints have
6057    * changed.
6058    */
6059   if (configure_request_pos_changed ||
6060       configure_request_size_changed ||
6061       hints_changed ||
6062       info->position_constraints_changed)
6063     {
6064       /* We request the constrained position if:
6065        *  - we were changing position, and need to clamp
6066        *    the change to the constraint
6067        *  - we're changing the size anyway
6068        *  - set_position() was called to toggle CENTER_ALWAYS on
6069        */
6070
6071       gtk_window_constrain_position (window,
6072                                      new_request.width,
6073                                      new_request.height,
6074                                      &new_request.x,
6075                                      &new_request.y);
6076       
6077       /* Update whether we need to request a move */
6078       if (info->last.configure_request.x != new_request.x ||
6079           info->last.configure_request.y != new_request.y)
6080         configure_request_pos_changed = TRUE;
6081       else
6082         configure_request_pos_changed = FALSE;
6083     }
6084
6085 #if 0
6086   if (window->type == GTK_WINDOW_TOPLEVEL)
6087     {
6088       int notify_x, notify_y;
6089
6090       /* this is the position from the last configure notify */
6091       gdk_window_get_position (widget->window, &notify_x, &notify_y);
6092     
6093       g_message ("--- %s ---\n"
6094                  "last  : %d,%d\t%d x %d\n"
6095                  "this  : %d,%d\t%d x %d\n"
6096                  "alloc : %d,%d\t%d x %d\n"
6097                  "req   :      \t%d x %d\n"
6098                  "resize:      \t%d x %d\n" 
6099                  "size_changed: %d pos_changed: %d hints_changed: %d\n"
6100                  "configure_notify_received: %d\n"
6101                  "configure_request_count: %d\n"
6102                  "position_constraints_changed: %d\n",
6103                  window->title ? window->title : "(no title)",
6104                  info->last.configure_request.x,
6105                  info->last.configure_request.y,
6106                  info->last.configure_request.width,
6107                  info->last.configure_request.height,
6108                  new_request.x,
6109                  new_request.y,
6110                  new_request.width,
6111                  new_request.height,
6112                  notify_x, notify_y,
6113                  widget->allocation.width,
6114                  widget->allocation.height,
6115                  widget->requisition.width,
6116                  widget->requisition.height,
6117                  info->resize_width,
6118                  info->resize_height,
6119                  configure_request_pos_changed,
6120                  configure_request_size_changed,
6121                  hints_changed,
6122                  window->configure_notify_received,
6123                  window->configure_request_count,
6124                  info->position_constraints_changed);
6125     }
6126 #endif
6127   
6128   saved_last_info = info->last;
6129   info->last.geometry = new_geometry;
6130   info->last.flags = new_flags;
6131   info->last.configure_request = new_request;
6132   
6133   /* need to set PPosition so the WM will look at our position,
6134    * but we don't want to count PPosition coming and going as a hints
6135    * change for future iterations. So we saved info->last prior to
6136    * this.
6137    */
6138   
6139   /* Also, if the initial position was explicitly set, then we always
6140    * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
6141    * work.
6142    */
6143
6144   /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
6145    * this is an initial map
6146    */
6147   
6148   if ((configure_request_pos_changed ||
6149        info->initial_pos_set ||
6150        (window->need_default_position &&
6151         get_effective_position (window) != GTK_WIN_POS_NONE)) &&
6152       (new_flags & GDK_HINT_POS) == 0)
6153     {
6154       new_flags |= GDK_HINT_POS;
6155       hints_changed = TRUE;
6156     }
6157   
6158   /* Set hints if necessary
6159    */
6160   if (hints_changed)
6161     gdk_window_set_geometry_hints (widget->window,
6162                                    &new_geometry,
6163                                    new_flags);
6164   
6165   /* handle resizing/moving and widget tree allocation
6166    */
6167   if (window->configure_notify_received)
6168     { 
6169       GtkAllocation allocation;
6170
6171       /* If we have received a configure event since
6172        * the last time in this function, we need to
6173        * accept our new size and size_allocate child widgets.
6174        * (see gtk_window_configure_event() for more details).
6175        *
6176        * 1 or more configure notifies may have been received.
6177        * Also, configure_notify_received will only be TRUE
6178        * if all expected configure notifies have been received
6179        * (one per configure request), as an optimization.
6180        *
6181        */
6182       window->configure_notify_received = FALSE;
6183
6184       /* gtk_window_configure_event() filled in widget->allocation */
6185       allocation = widget->allocation;
6186       gtk_widget_size_allocate (widget, &allocation);
6187
6188       gdk_window_process_updates (widget->window, TRUE);
6189       
6190       gdk_window_configure_finished (widget->window);
6191
6192       /* If the configure request changed, it means that
6193        * we either:
6194        *   1) coincidentally changed hints or widget properties
6195        *      impacting the configure request before getting
6196        *      a configure notify, or
6197        *   2) some broken widget is changing its size request
6198        *      during size allocation, resulting in
6199        *      a false appearance of changed configure request.
6200        *
6201        * For 1), we could just go ahead and ask for the
6202        * new size right now, but doing that for 2)
6203        * might well be fighting the user (and can even
6204        * trigger a loop). Since we really don't want to
6205        * do that, we requeue a resize in hopes that
6206        * by the time it gets handled, the child has seen
6207        * the light and is willing to go along with the
6208        * new size. (this happens for the zvt widget, since
6209        * the size_allocate() above will have stored the
6210        * requisition corresponding to the new size in the
6211        * zvt widget)
6212        *
6213        * This doesn't buy us anything for 1), but it shouldn't
6214        * hurt us too badly, since it is what would have
6215        * happened if we had gotten the configure event before
6216        * the new size had been set.
6217        */
6218
6219       if (configure_request_size_changed ||
6220           configure_request_pos_changed)
6221         {
6222           /* Don't change the recorded last info after all, because we
6223            * haven't actually updated to the new info yet - we decided
6224            * to postpone our configure request until later.
6225            */
6226           info->last = saved_last_info;
6227           
6228           gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
6229         }
6230
6231       return;                   /* Bail out, we didn't really process the move/resize */
6232     }
6233   else if ((configure_request_size_changed || hints_changed) &&
6234            (widget->allocation.width != new_request.width ||
6235             widget->allocation.height != new_request.height))
6236
6237     {
6238       /* We are in one of the following situations:
6239        * A. configure_request_size_changed
6240        *    our requisition has changed and we need a different window size,
6241        *    so we request it from the window manager.
6242        * B. !configure_request_size_changed && hints_changed
6243        *    the window manager rejects our size, but we have just changed the
6244        *    window manager hints, so there's a chance our request will
6245        *    be honoured this time, so we try again.
6246        *
6247        * However, if the new requisition is the same as the current allocation,
6248        * we don't request it again, since we won't get a ConfigureNotify back from
6249        * the window manager unless it decides to change our requisition. If
6250        * we don't get the ConfigureNotify back, the resize queue will never be run.
6251        */
6252
6253       /* Now send the configure request */
6254       if (configure_request_pos_changed)
6255         {
6256           if (window->frame)
6257             {
6258               gdk_window_move_resize (window->frame,
6259                                       new_request.x - window->frame_left,
6260                                       new_request.y - window->frame_top,
6261                                       new_request.width + window->frame_left + window->frame_right,
6262                                       new_request.height + window->frame_top + window->frame_bottom);
6263               gdk_window_resize (widget->window,
6264                                  new_request.width, new_request.height);
6265             }
6266           else
6267             gdk_window_move_resize (widget->window,
6268                                     new_request.x, new_request.y,
6269                                     new_request.width, new_request.height);
6270         }
6271       else  /* only size changed */
6272         {
6273           if (window->frame)
6274             gdk_window_resize (window->frame,
6275                                new_request.width + window->frame_left + window->frame_right,
6276                                new_request.height + window->frame_top + window->frame_bottom);
6277           gdk_window_resize (widget->window,
6278                              new_request.width, new_request.height);
6279         }
6280       
6281       if (window->type == GTK_WINDOW_POPUP)
6282         {
6283           GtkAllocation allocation;
6284
6285           /* Directly size allocate for override redirect (popup) windows. */
6286           allocation.x = 0;
6287           allocation.y = 0;
6288           allocation.width = new_request.width;
6289           allocation.height = new_request.height;
6290
6291           gtk_widget_size_allocate (widget, &allocation);
6292
6293           gdk_window_process_updates (widget->window, TRUE);
6294
6295           if (container->resize_mode == GTK_RESIZE_QUEUE)
6296             gtk_widget_queue_draw (widget);
6297         }
6298       else
6299         {
6300           /* Increment the number of have-not-yet-received-notify requests */
6301           window->configure_request_count += 1;
6302           gdk_window_freeze_toplevel_updates_libgtk_only (widget->window);
6303
6304           /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
6305            * configure event in response to our resizing request.
6306            * the configure event will cause a new resize with
6307            * ->configure_notify_received=TRUE.
6308            * until then, we want to
6309            * - discard expose events
6310            * - coalesce resizes for our children
6311            * - defer any window resizes until the configure event arrived
6312            * to achieve this, we queue a resize for the window, but remove its
6313            * resizing handler, so resizing will not be handled from the next
6314            * idle handler but when the configure event arrives.
6315            *
6316            * FIXME: we should also dequeue the pending redraws here, since
6317            * we handle those ourselves upon ->configure_notify_received==TRUE.
6318            */
6319           if (container->resize_mode == GTK_RESIZE_QUEUE)
6320             {
6321               gtk_widget_queue_resize_no_redraw (widget);
6322               _gtk_container_dequeue_resize_handler (container);
6323             }
6324         }
6325     }
6326   else
6327     {
6328       /* Handle any position changes.
6329        */
6330       if (configure_request_pos_changed)
6331         {
6332           if (window->frame)
6333             {
6334               gdk_window_move (window->frame,
6335                                new_request.x - window->frame_left,
6336                                new_request.y - window->frame_top);
6337             }
6338           else
6339             gdk_window_move (widget->window,
6340                              new_request.x, new_request.y);
6341         }
6342
6343       /* And run the resize queue.
6344        */
6345       gtk_container_resize_children (container);
6346     }
6347   
6348   /* We have now processed a move/resize since the last position
6349    * constraint change, setting of the initial position, or resize.
6350    * (Not resetting these flags here can lead to infinite loops for
6351    * GTK_RESIZE_IMMEDIATE containers)
6352    */
6353   info->position_constraints_changed = FALSE;
6354   info->initial_pos_set = FALSE;
6355   info->resize_width = -1;
6356   info->resize_height = -1;
6357 }
6358
6359 /* Compare two sets of Geometry hints for equality.
6360  */
6361 static gboolean
6362 gtk_window_compare_hints (GdkGeometry *geometry_a,
6363                           guint        flags_a,
6364                           GdkGeometry *geometry_b,
6365                           guint        flags_b)
6366 {
6367   if (flags_a != flags_b)
6368     return FALSE;
6369   
6370   if ((flags_a & GDK_HINT_MIN_SIZE) &&
6371       (geometry_a->min_width != geometry_b->min_width ||
6372        geometry_a->min_height != geometry_b->min_height))
6373     return FALSE;
6374
6375   if ((flags_a & GDK_HINT_MAX_SIZE) &&
6376       (geometry_a->max_width != geometry_b->max_width ||
6377        geometry_a->max_height != geometry_b->max_height))
6378     return FALSE;
6379
6380   if ((flags_a & GDK_HINT_BASE_SIZE) &&
6381       (geometry_a->base_width != geometry_b->base_width ||
6382        geometry_a->base_height != geometry_b->base_height))
6383     return FALSE;
6384
6385   if ((flags_a & GDK_HINT_ASPECT) &&
6386       (geometry_a->min_aspect != geometry_b->min_aspect ||
6387        geometry_a->max_aspect != geometry_b->max_aspect))
6388     return FALSE;
6389
6390   if ((flags_a & GDK_HINT_RESIZE_INC) &&
6391       (geometry_a->width_inc != geometry_b->width_inc ||
6392        geometry_a->height_inc != geometry_b->height_inc))
6393     return FALSE;
6394
6395   if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
6396       geometry_a->win_gravity != geometry_b->win_gravity)
6397     return FALSE;
6398
6399   return TRUE;
6400 }
6401
6402 void
6403 _gtk_window_constrain_size (GtkWindow   *window,
6404                             gint         width,
6405                             gint         height,
6406                             gint        *new_width,
6407                             gint        *new_height)
6408 {
6409   GtkWindowGeometryInfo *info;
6410
6411   g_return_if_fail (GTK_IS_WINDOW (window));
6412
6413   info = window->geometry_info;
6414   if (info)
6415     {
6416       GdkWindowHints flags = info->last.flags;
6417       GdkGeometry *geometry = &info->last.geometry;
6418       
6419       gtk_window_constrain_size (window,
6420                                  geometry,
6421                                  flags,
6422                                  width,
6423                                  height,
6424                                  new_width,
6425                                  new_height);
6426     }
6427 }
6428
6429 static void 
6430 gtk_window_constrain_size (GtkWindow   *window,
6431                            GdkGeometry *geometry,
6432                            guint        flags,
6433                            gint         width,
6434                            gint         height,
6435                            gint        *new_width,
6436                            gint        *new_height)
6437 {
6438   gdk_window_constrain_size (geometry, flags, width, height,
6439                              new_width, new_height);
6440 }
6441
6442 /* Compute the set of geometry hints and flags for a window
6443  * based on the application set geometry, and requisiition
6444  * of the window. gtk_widget_size_request() must have been
6445  * called first.
6446  */
6447 static void
6448 gtk_window_compute_hints (GtkWindow   *window,
6449                           GdkGeometry *new_geometry,
6450                           guint       *new_flags)
6451 {
6452   GtkWidget *widget;
6453   gint extra_width = 0;
6454   gint extra_height = 0;
6455   GtkWindowGeometryInfo *geometry_info;
6456   GtkRequisition requisition;
6457
6458   widget = GTK_WIDGET (window);
6459   
6460   gtk_widget_get_child_requisition (widget, &requisition);
6461   geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
6462
6463   if (geometry_info)
6464     {
6465       *new_flags = geometry_info->mask;
6466       *new_geometry = geometry_info->geometry;
6467     }
6468   else
6469     {
6470       *new_flags = 0;
6471     }
6472   
6473   if (geometry_info && geometry_info->widget)
6474     {
6475       GtkRequisition child_requisition;
6476
6477       /* FIXME: This really isn't right. It gets the min size wrong and forces
6478        * callers to do horrible hacks like set a huge usize on the child requisition
6479        * to get the base size right. We really want to find the answers to:
6480        *
6481        *  - If the geometry widget was infinitely big, how much extra space
6482        *    would be needed for the stuff around it.
6483        *
6484        *  - If the geometry widget was infinitely small, how big would the
6485        *    window still have to be.
6486        *
6487        * Finding these answers would be a bit of a mess here. (Bug #68668)
6488        */
6489       gtk_widget_get_child_requisition (geometry_info->widget, &child_requisition);
6490       
6491       extra_width = widget->requisition.width - child_requisition.width;
6492       extra_height = widget->requisition.height - child_requisition.height;
6493     }
6494
6495   /* We don't want to set GDK_HINT_POS in here, we just set it
6496    * in gtk_window_move_resize() when we want the position
6497    * honored.
6498    */
6499   
6500   if (*new_flags & GDK_HINT_BASE_SIZE)
6501     {
6502       new_geometry->base_width += extra_width;
6503       new_geometry->base_height += extra_height;
6504     }
6505   else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
6506            (*new_flags & GDK_HINT_RESIZE_INC) &&
6507            ((extra_width != 0) || (extra_height != 0)))
6508     {
6509       *new_flags |= GDK_HINT_BASE_SIZE;
6510       
6511       new_geometry->base_width = extra_width;
6512       new_geometry->base_height = extra_height;
6513     }
6514   
6515   if (*new_flags & GDK_HINT_MIN_SIZE)
6516     {
6517       if (new_geometry->min_width < 0)
6518         new_geometry->min_width = requisition.width;
6519       else
6520         new_geometry->min_width += extra_width;
6521
6522       if (new_geometry->min_height < 0)
6523         new_geometry->min_height = requisition.height;
6524       else
6525         new_geometry->min_height += extra_height;
6526     }
6527   else if (!window->allow_shrink)
6528     {
6529       *new_flags |= GDK_HINT_MIN_SIZE;
6530       
6531       new_geometry->min_width = requisition.width;
6532       new_geometry->min_height = requisition.height;
6533     }
6534   
6535   if (*new_flags & GDK_HINT_MAX_SIZE)
6536     {
6537       if (new_geometry->max_width < 0)
6538         new_geometry->max_width = requisition.width;
6539       else
6540         new_geometry->max_width += extra_width;
6541
6542       if (new_geometry->max_height < 0)
6543         new_geometry->max_height = requisition.height;
6544       else
6545         new_geometry->max_height += extra_height;
6546     }
6547   else if (!window->allow_grow)
6548     {
6549       *new_flags |= GDK_HINT_MAX_SIZE;
6550       
6551       new_geometry->max_width = requisition.width;
6552       new_geometry->max_height = requisition.height;
6553     }
6554
6555   *new_flags |= GDK_HINT_WIN_GRAVITY;
6556   new_geometry->win_gravity = window->gravity;
6557 }
6558
6559 /***********************
6560  * Redrawing functions *
6561  ***********************/
6562
6563 static void
6564 gtk_window_paint (GtkWidget     *widget,
6565                   GdkRectangle *area)
6566 {
6567   gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL, 
6568                       GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
6569 }
6570
6571 static gint
6572 gtk_window_expose (GtkWidget      *widget,
6573                    GdkEventExpose *event)
6574 {
6575   if (!GTK_WIDGET_APP_PAINTABLE (widget))
6576     gtk_window_paint (widget, &event->area);
6577   
6578   if (GTK_WIDGET_CLASS (gtk_window_parent_class)->expose_event)
6579     return GTK_WIDGET_CLASS (gtk_window_parent_class)->expose_event (widget, event);
6580
6581   return FALSE;
6582 }
6583
6584 /**
6585  * gtk_window_set_has_frame:
6586  * @window: a #GtkWindow
6587  * @setting: a boolean
6588  *
6589  * (Note: this is a special-purpose function for the framebuffer port,
6590  *  that causes GTK+ to draw its own window border. For most applications,
6591  *  you want gtk_window_set_decorated() instead, which tells the window
6592  *  manager whether to draw the window border.)
6593  * 
6594  * If this function is called on a window with setting of %TRUE, before
6595  * it is realized or showed, it will have a "frame" window around
6596  * @window->window, accessible in @window->frame. Using the signal 
6597  * frame_event you can receive all events targeted at the frame.
6598  * 
6599  * This function is used by the linux-fb port to implement managed
6600  * windows, but it could conceivably be used by X-programs that
6601  * want to do their own window decorations.
6602  *
6603  **/
6604 void
6605 gtk_window_set_has_frame (GtkWindow *window, 
6606                           gboolean   setting)
6607 {
6608   g_return_if_fail (GTK_IS_WINDOW (window));
6609   g_return_if_fail (!GTK_WIDGET_REALIZED (window));
6610
6611   window->has_frame = setting != FALSE;
6612 }
6613
6614 /**
6615  * gtk_window_get_has_frame:
6616  * @window: a #GtkWindow
6617  * 
6618  * Accessor for whether the window has a frame window exterior to
6619  * @window->window. Gets the value set by gtk_window_set_has_frame ().
6620  *
6621  * Return value: %TRUE if a frame has been added to the window
6622  *   via gtk_window_set_has_frame().
6623  **/
6624 gboolean
6625 gtk_window_get_has_frame (GtkWindow *window)
6626 {
6627   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6628
6629   return window->has_frame;
6630 }
6631
6632 /**
6633  * gtk_window_set_frame_dimensions:
6634  * @window: a #GtkWindow that has a frame
6635  * @left: The width of the left border
6636  * @top: The height of the top border
6637  * @right: The width of the right border
6638  * @bottom: The height of the bottom border
6639  *
6640  * (Note: this is a special-purpose function intended for the framebuffer
6641  *  port; see gtk_window_set_has_frame(). It will have no effect on the
6642  *  window border drawn by the window manager, which is the normal
6643  *  case when using the X Window system.)
6644  *
6645  * For windows with frames (see gtk_window_set_has_frame()) this function
6646  * can be used to change the size of the frame border.
6647  **/
6648 void
6649 gtk_window_set_frame_dimensions (GtkWindow *window, 
6650                                  gint       left,
6651                                  gint       top,
6652                                  gint       right,
6653                                  gint       bottom)
6654 {
6655   GtkWidget *widget;
6656
6657   g_return_if_fail (GTK_IS_WINDOW (window));
6658
6659   widget = GTK_WIDGET (window);
6660
6661   if (window->frame_left == left &&
6662       window->frame_top == top &&
6663       window->frame_right == right && 
6664       window->frame_bottom == bottom)
6665     return;
6666
6667   window->frame_left = left;
6668   window->frame_top = top;
6669   window->frame_right = right;
6670   window->frame_bottom = bottom;
6671
6672   if (GTK_WIDGET_REALIZED (widget) && window->frame)
6673     {
6674       gint width = widget->allocation.width + left + right;
6675       gint height = widget->allocation.height + top + bottom;
6676       gdk_window_resize (window->frame, width, height);
6677       gtk_decorated_window_move_resize_window (window,
6678                                                left, top,
6679                                                widget->allocation.width,
6680                                                widget->allocation.height);
6681     }
6682 }
6683
6684 /**
6685  * gtk_window_present:
6686  * @window: a #GtkWindow
6687  *
6688  * Presents a window to the user. This may mean raising the window
6689  * in the stacking order, deiconifying it, moving it to the current
6690  * desktop, and/or giving it the keyboard focus, possibly dependent
6691  * on the user's platform, window manager, and preferences.
6692  *
6693  * If @window is hidden, this function calls gtk_widget_show()
6694  * as well.
6695  * 
6696  * This function should be used when the user tries to open a window
6697  * that's already open. Say for example the preferences dialog is
6698  * currently open, and the user chooses Preferences from the menu
6699  * a second time; use gtk_window_present() to move the already-open dialog
6700  * where the user can see it.
6701  *
6702  * If you are calling this function in response to a user interaction,
6703  * it is preferable to use gtk_window_present_with_time().
6704  * 
6705  **/
6706 void
6707 gtk_window_present (GtkWindow *window)
6708 {
6709   gtk_window_present_with_time (window, GDK_CURRENT_TIME);
6710 }
6711
6712 /**
6713  * gtk_window_present_with_time:
6714  * @window: a #GtkWindow
6715  * @timestamp: the timestamp of the user interaction (typically a 
6716  *   button or key press event) which triggered this call
6717  *
6718  * Presents a window to the user in response to a user interaction.
6719  * If you need to present a window without a timestamp, use 
6720  * gtk_window_present(). See gtk_window_present() for details. 
6721  * 
6722  * Since: 2.8
6723  **/
6724 void
6725 gtk_window_present_with_time (GtkWindow *window,
6726                               guint32    timestamp)
6727 {
6728   GtkWidget *widget;
6729
6730   g_return_if_fail (GTK_IS_WINDOW (window));
6731
6732   widget = GTK_WIDGET (window);
6733
6734   if (GTK_WIDGET_VISIBLE (window))
6735     {
6736       g_assert (widget->window != NULL);
6737       
6738       gdk_window_show (widget->window);
6739
6740       /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
6741       if (timestamp == GDK_CURRENT_TIME)
6742         {
6743 #ifdef GDK_WINDOWING_X11
6744           GdkDisplay *display;
6745
6746           display = gtk_widget_get_display (GTK_WIDGET (window));
6747           timestamp = gdk_x11_display_get_user_time (display);
6748 #else
6749           timestamp = gtk_get_current_event_time ();
6750 #endif
6751         }
6752
6753       gdk_window_focus (widget->window, timestamp);
6754     }
6755   else
6756     {
6757       gtk_widget_show (widget);
6758     }
6759 }
6760
6761 /**
6762  * gtk_window_iconify:
6763  * @window: a #GtkWindow
6764  *
6765  * Asks to iconify (i.e. minimize) the specified @window. Note that
6766  * you shouldn't assume the window is definitely iconified afterward,
6767  * because other entities (e.g. the user or <link
6768  * linkend="gtk-X11-arch">window manager</link>) could deiconify it
6769  * again, or there may not be a window manager in which case
6770  * iconification isn't possible, etc. But normally the window will end
6771  * up iconified. Just don't write code that crashes if not.
6772  *
6773  * It's permitted to call this function before showing a window,
6774  * in which case the window will be iconified before it ever appears
6775  * onscreen.
6776  *
6777  * You can track iconification via the "window-state-event" signal
6778  * on #GtkWidget.
6779  * 
6780  **/
6781 void
6782 gtk_window_iconify (GtkWindow *window)
6783 {
6784   GtkWidget *widget;
6785   GdkWindow *toplevel;
6786   
6787   g_return_if_fail (GTK_IS_WINDOW (window));
6788
6789   widget = GTK_WIDGET (window);
6790
6791   window->iconify_initially = TRUE;
6792
6793   if (window->frame)
6794     toplevel = window->frame;
6795   else
6796     toplevel = widget->window;
6797   
6798   if (toplevel != NULL)
6799     gdk_window_iconify (toplevel);
6800 }
6801
6802 /**
6803  * gtk_window_deiconify:
6804  * @window: a #GtkWindow
6805  *
6806  * Asks to deiconify (i.e. unminimize) the specified @window. Note
6807  * that you shouldn't assume the window is definitely deiconified
6808  * afterward, because other entities (e.g. the user or <link
6809  * linkend="gtk-X11-arch">window manager</link>) could iconify it
6810  * again before your code which assumes deiconification gets to run.
6811  *
6812  * You can track iconification via the "window-state-event" signal
6813  * on #GtkWidget.
6814  **/
6815 void
6816 gtk_window_deiconify (GtkWindow *window)
6817 {
6818   GtkWidget *widget;
6819   GdkWindow *toplevel;
6820   
6821   g_return_if_fail (GTK_IS_WINDOW (window));
6822
6823   widget = GTK_WIDGET (window);
6824
6825   window->iconify_initially = FALSE;
6826
6827   if (window->frame)
6828     toplevel = window->frame;
6829   else
6830     toplevel = widget->window;
6831   
6832   if (toplevel != NULL)
6833     gdk_window_deiconify (toplevel);
6834 }
6835
6836 /**
6837  * gtk_window_stick:
6838  * @window: a #GtkWindow
6839  *
6840  * Asks to stick @window, which means that it will appear on all user
6841  * desktops. Note that you shouldn't assume the window is definitely
6842  * stuck afterward, because other entities (e.g. the user or <link
6843  * linkend="gtk-X11-arch">window manager</link>) could unstick it
6844  * again, and some window managers do not support sticking
6845  * windows. But normally the window will end up stuck. Just don't
6846  * write code that crashes if not.
6847  *
6848  * It's permitted to call this function before showing a window.
6849  *
6850  * You can track stickiness via the "window-state-event" signal
6851  * on #GtkWidget.
6852  * 
6853  **/
6854 void
6855 gtk_window_stick (GtkWindow *window)
6856 {
6857   GtkWidget *widget;
6858   GdkWindow *toplevel;
6859   
6860   g_return_if_fail (GTK_IS_WINDOW (window));
6861
6862   widget = GTK_WIDGET (window);
6863
6864   window->stick_initially = TRUE;
6865
6866   if (window->frame)
6867     toplevel = window->frame;
6868   else
6869     toplevel = widget->window;
6870   
6871   if (toplevel != NULL)
6872     gdk_window_stick (toplevel);
6873 }
6874
6875 /**
6876  * gtk_window_unstick:
6877  * @window: a #GtkWindow
6878  *
6879  * Asks to unstick @window, which means that it will appear on only
6880  * one of the user's desktops. Note that you shouldn't assume the
6881  * window is definitely unstuck afterward, because other entities
6882  * (e.g. the user or <link linkend="gtk-X11-arch">window
6883  * manager</link>) could stick it again. But normally the window will
6884  * end up stuck. Just don't write code that crashes if not.
6885  *
6886  * You can track stickiness via the "window-state-event" signal
6887  * on #GtkWidget.
6888  * 
6889  **/
6890 void
6891 gtk_window_unstick (GtkWindow *window)
6892 {
6893   GtkWidget *widget;
6894   GdkWindow *toplevel;
6895   
6896   g_return_if_fail (GTK_IS_WINDOW (window));
6897
6898   widget = GTK_WIDGET (window);
6899
6900   window->stick_initially = FALSE;
6901
6902   if (window->frame)
6903     toplevel = window->frame;
6904   else
6905     toplevel = widget->window;
6906   
6907   if (toplevel != NULL)
6908     gdk_window_unstick (toplevel);
6909 }
6910
6911 /**
6912  * gtk_window_maximize:
6913  * @window: a #GtkWindow
6914  *
6915  * Asks to maximize @window, so that it becomes full-screen. Note that
6916  * you shouldn't assume the window is definitely maximized afterward,
6917  * because other entities (e.g. the user or <link
6918  * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
6919  * again, and not all window managers support maximization. But
6920  * normally the window will end up maximized. Just don't write code
6921  * that crashes if not.
6922  *
6923  * It's permitted to call this function before showing a window,
6924  * in which case the window will be maximized when it appears onscreen
6925  * initially.
6926  *
6927  * You can track maximization via the "window-state-event" signal
6928  * on #GtkWidget.
6929  * 
6930  **/
6931 void
6932 gtk_window_maximize (GtkWindow *window)
6933 {
6934   GtkWidget *widget;
6935   GdkWindow *toplevel;
6936   
6937   g_return_if_fail (GTK_IS_WINDOW (window));
6938
6939   widget = GTK_WIDGET (window);
6940
6941   window->maximize_initially = TRUE;
6942
6943   if (window->frame)
6944     toplevel = window->frame;
6945   else
6946     toplevel = widget->window;
6947   
6948   if (toplevel != NULL)
6949     gdk_window_maximize (toplevel);
6950 }
6951
6952 /**
6953  * gtk_window_unmaximize:
6954  * @window: a #GtkWindow
6955  *
6956  * Asks to unmaximize @window. Note that you shouldn't assume the
6957  * window is definitely unmaximized afterward, because other entities
6958  * (e.g. the user or <link linkend="gtk-X11-arch">window
6959  * manager</link>) could maximize it again, and not all window
6960  * managers honor requests to unmaximize. But normally the window will
6961  * end up unmaximized. Just don't write code that crashes if not.
6962  *
6963  * You can track maximization via the "window-state-event" signal
6964  * on #GtkWidget.
6965  * 
6966  **/
6967 void
6968 gtk_window_unmaximize (GtkWindow *window)
6969 {
6970   GtkWidget *widget;
6971   GdkWindow *toplevel;
6972   
6973   g_return_if_fail (GTK_IS_WINDOW (window));
6974
6975   widget = GTK_WIDGET (window);
6976
6977   window->maximize_initially = FALSE;
6978
6979   if (window->frame)
6980     toplevel = window->frame;
6981   else
6982     toplevel = widget->window;
6983   
6984   if (toplevel != NULL)
6985     gdk_window_unmaximize (toplevel);
6986 }
6987
6988 /**
6989  * gtk_window_fullscreen:
6990  * @window: a #GtkWindow
6991  *
6992  * Asks to place @window in the fullscreen state. Note that you
6993  * shouldn't assume the window is definitely full screen afterward,
6994  * because other entities (e.g. the user or <link
6995  * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
6996  * again, and not all window managers honor requests to fullscreen
6997  * windows. But normally the window will end up fullscreen. Just
6998  * don't write code that crashes if not.
6999  *
7000  * You can track the fullscreen state via the "window-state-event" signal
7001  * on #GtkWidget.
7002  * 
7003  * Since: 2.2
7004  **/
7005 void
7006 gtk_window_fullscreen (GtkWindow *window)
7007 {
7008   GtkWidget *widget;
7009   GdkWindow *toplevel;
7010   GtkWindowPrivate *priv;
7011   
7012   g_return_if_fail (GTK_IS_WINDOW (window));
7013
7014   widget = GTK_WIDGET (window);
7015   priv = GTK_WINDOW_GET_PRIVATE (window);
7016   
7017   priv->fullscreen_initially = TRUE;
7018
7019   if (window->frame)
7020     toplevel = window->frame;
7021   else
7022     toplevel = widget->window;
7023   
7024   if (toplevel != NULL)
7025     gdk_window_fullscreen (toplevel);
7026 }
7027
7028 /**
7029  * gtk_window_unfullscreen:
7030  * @window: a #GtkWindow
7031  *
7032  * Asks to toggle off the fullscreen state for @window. Note that you
7033  * shouldn't assume the window is definitely not full screen
7034  * afterward, because other entities (e.g. the user or <link
7035  * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7036  * again, and not all window managers honor requests to unfullscreen
7037  * windows. But normally the window will end up restored to its normal
7038  * state. Just don't write code that crashes if not.
7039  *
7040  * You can track the fullscreen state via the "window-state-event" signal
7041  * on #GtkWidget.
7042  * 
7043  * Since: 2.2
7044  **/
7045 void
7046 gtk_window_unfullscreen (GtkWindow *window)
7047 {
7048   GtkWidget *widget;
7049   GdkWindow *toplevel;
7050   GtkWindowPrivate *priv;
7051   
7052   g_return_if_fail (GTK_IS_WINDOW (window));
7053
7054   widget = GTK_WIDGET (window);
7055   priv = GTK_WINDOW_GET_PRIVATE (window);
7056   
7057   priv->fullscreen_initially = FALSE;
7058
7059   if (window->frame)
7060     toplevel = window->frame;
7061   else
7062     toplevel = widget->window;
7063   
7064   if (toplevel != NULL)
7065     gdk_window_unfullscreen (toplevel);
7066 }
7067
7068 /**
7069  * gtk_window_set_keep_above:
7070  * @window: a #GtkWindow
7071  * @setting: whether to keep @window above other windows
7072  *
7073  * Asks to keep @window above, so that it stays on top. Note that
7074  * you shouldn't assume the window is definitely above afterward,
7075  * because other entities (e.g. the user or <link
7076  * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
7077  * and not all window managers support keeping windows above. But
7078  * normally the window will end kept above. Just don't write code
7079  * that crashes if not.
7080  *
7081  * It's permitted to call this function before showing a window,
7082  * in which case the window will be kept above when it appears onscreen
7083  * initially.
7084  *
7085  * You can track the above state via the "window-state-event" signal
7086  * on #GtkWidget.
7087  *
7088  * Note that, according to the <ulink 
7089  * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window 
7090  * Manager Hints</ulink> specification, the above state is mainly meant 
7091  * for user preferences and should not be used by applications e.g. for 
7092  * drawing attention to their dialogs.
7093  *
7094  * Since: 2.4
7095  **/
7096 void
7097 gtk_window_set_keep_above (GtkWindow *window,
7098                            gboolean   setting)
7099 {
7100   GtkWidget *widget;
7101   GtkWindowPrivate *priv;
7102   GdkWindow *toplevel;
7103
7104   g_return_if_fail (GTK_IS_WINDOW (window));
7105
7106   widget = GTK_WIDGET (window);
7107   priv = GTK_WINDOW_GET_PRIVATE (window);
7108
7109   priv->above_initially = setting != FALSE;
7110   if (setting)
7111     priv->below_initially = FALSE;
7112
7113   if (window->frame)
7114     toplevel = window->frame;
7115   else
7116     toplevel = widget->window;
7117
7118   if (toplevel != NULL)
7119     gdk_window_set_keep_above (toplevel, setting);
7120 }
7121
7122 /**
7123  * gtk_window_set_keep_below:
7124  * @window: a #GtkWindow
7125  * @setting: whether to keep @window below other windows
7126  *
7127  * Asks to keep @window below, so that it stays in bottom. Note that
7128  * you shouldn't assume the window is definitely below afterward,
7129  * because other entities (e.g. the user or <link
7130  * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
7131  * and not all window managers support putting windows below. But
7132  * normally the window will be kept below. Just don't write code
7133  * that crashes if not.
7134  *
7135  * It's permitted to call this function before showing a window,
7136  * in which case the window will be kept below when it appears onscreen
7137  * initially.
7138  *
7139  * You can track the below state via the "window-state-event" signal
7140  * on #GtkWidget.
7141  *
7142  * Note that, according to the <ulink 
7143  * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window 
7144  * Manager Hints</ulink> specification, the above state is mainly meant 
7145  * for user preferences and should not be used by applications e.g. for 
7146  * drawing attention to their dialogs.
7147  *
7148  * Since: 2.4
7149  **/
7150 void
7151 gtk_window_set_keep_below (GtkWindow *window,
7152                            gboolean   setting)
7153 {
7154   GtkWidget *widget;
7155   GtkWindowPrivate *priv;
7156   GdkWindow *toplevel;
7157
7158   g_return_if_fail (GTK_IS_WINDOW (window));
7159
7160   widget = GTK_WIDGET (window);
7161   priv = GTK_WINDOW_GET_PRIVATE (window);
7162
7163   priv->below_initially = setting != FALSE;
7164   if (setting)
7165     priv->above_initially = FALSE;
7166
7167   if (window->frame)
7168     toplevel = window->frame;
7169   else
7170     toplevel = widget->window;
7171
7172   if (toplevel != NULL)
7173     gdk_window_set_keep_below (toplevel, setting);
7174 }
7175
7176 /**
7177  * gtk_window_set_resizable:
7178  * @window: a #GtkWindow
7179  * @resizable: %TRUE if the user can resize this window
7180  *
7181  * Sets whether the user can resize a window. Windows are user resizable
7182  * by default.
7183  **/
7184 void
7185 gtk_window_set_resizable (GtkWindow *window,
7186                           gboolean   resizable)
7187 {
7188   g_return_if_fail (GTK_IS_WINDOW (window));
7189
7190   gtk_window_set_policy_internal (window, FALSE, resizable, FALSE);
7191 }
7192
7193 /**
7194  * gtk_window_get_resizable:
7195  * @window: a #GtkWindow
7196  *
7197  * Gets the value set by gtk_window_set_resizable().
7198  *
7199  * Return value: %TRUE if the user can resize the window
7200  **/
7201 gboolean
7202 gtk_window_get_resizable (GtkWindow *window)
7203 {
7204   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7205
7206   /* allow_grow is most likely to indicate the semantic concept we
7207    * mean by "resizable" (and will be a reliable indicator if
7208    * set_policy() hasn't been called)
7209    */
7210   return window->allow_grow;
7211 }
7212
7213 /**
7214  * gtk_window_set_gravity:
7215  * @window: a #GtkWindow
7216  * @gravity: window gravity
7217  *
7218  * Window gravity defines the meaning of coordinates passed to
7219  * gtk_window_move(). See gtk_window_move() and #GdkGravity for
7220  * more details.
7221  *
7222  * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
7223  * typically "do what you mean."
7224  *
7225  **/
7226 void
7227 gtk_window_set_gravity (GtkWindow *window,
7228                         GdkGravity gravity)
7229 {
7230   g_return_if_fail (GTK_IS_WINDOW (window));
7231
7232   if (gravity != window->gravity)
7233     {
7234       window->gravity = gravity;
7235
7236       /* gtk_window_move_resize() will adapt gravity
7237        */
7238       gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7239
7240       g_object_notify (G_OBJECT (window), "gravity");
7241     }
7242 }
7243
7244 /**
7245  * gtk_window_get_gravity:
7246  * @window: a #GtkWindow
7247  *
7248  * Gets the value set by gtk_window_set_gravity().
7249  *
7250  * Return value: window gravity
7251  **/
7252 GdkGravity
7253 gtk_window_get_gravity (GtkWindow *window)
7254 {
7255   g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
7256
7257   return window->gravity;
7258 }
7259
7260 /**
7261  * gtk_window_begin_resize_drag:
7262  * @window: a #GtkWindow
7263  * @button: mouse button that initiated the drag
7264  * @edge: position of the resize control
7265  * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7266  * @root_y: Y position where the user clicked to initiate the drag
7267  * @timestamp: timestamp from the click event that initiated the drag
7268  *
7269  * Starts resizing a window. This function is used if an application
7270  * has window resizing controls. When GDK can support it, the resize
7271  * will be done using the standard mechanism for the <link
7272  * linkend="gtk-X11-arch">window manager</link> or windowing
7273  * system. Otherwise, GDK will try to emulate window resizing,
7274  * potentially not all that well, depending on the windowing system.
7275  * 
7276  **/
7277 void
7278 gtk_window_begin_resize_drag  (GtkWindow    *window,
7279                                GdkWindowEdge edge,
7280                                gint          button,
7281                                gint          root_x,
7282                                gint          root_y,
7283                                guint32       timestamp)
7284 {
7285   GtkWidget *widget;
7286   GdkWindow *toplevel;
7287   
7288   g_return_if_fail (GTK_IS_WINDOW (window));
7289   g_return_if_fail (GTK_WIDGET_VISIBLE (window));
7290   
7291   widget = GTK_WIDGET (window);
7292   
7293   if (window->frame)
7294     toplevel = window->frame;
7295   else
7296     toplevel = widget->window;
7297   
7298   gdk_window_begin_resize_drag (toplevel,
7299                                 edge, button,
7300                                 root_x, root_y,
7301                                 timestamp);
7302 }
7303
7304 /**
7305  * gtk_window_get_frame_dimensions:
7306  * @window: a #GtkWindow
7307  * @left: location to store the width of the frame at the left, or %NULL
7308  * @top: location to store the height of the frame at the top, or %NULL
7309  * @right: location to store the width of the frame at the returns, or %NULL
7310  * @bottom: location to store the height of the frame at the bottom, or %NULL
7311  *
7312  * (Note: this is a special-purpose function intended for the
7313  *  framebuffer port; see gtk_window_set_has_frame(). It will not
7314  *  return the size of the window border drawn by the <link
7315  *  linkend="gtk-X11-arch">window manager</link>, which is the normal
7316  *  case when using a windowing system.  See
7317  *  gdk_window_get_frame_extents() to get the standard window border
7318  *  extents.)
7319  * 
7320  * Retrieves the dimensions of the frame window for this toplevel.
7321  * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
7322  **/
7323 void
7324 gtk_window_get_frame_dimensions (GtkWindow *window,
7325                                  gint      *left,
7326                                  gint      *top,
7327                                  gint      *right,
7328                                  gint      *bottom)
7329 {
7330   g_return_if_fail (GTK_IS_WINDOW (window));
7331
7332   if (left)
7333     *left = window->frame_left;
7334   if (top)
7335     *top = window->frame_top;
7336   if (right)
7337     *right = window->frame_right;
7338   if (bottom)
7339     *bottom = window->frame_bottom;
7340 }
7341
7342 /**
7343  * gtk_window_begin_move_drag:
7344  * @window: a #GtkWindow
7345  * @button: mouse button that initiated the drag
7346  * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7347  * @root_y: Y position where the user clicked to initiate the drag
7348  * @timestamp: timestamp from the click event that initiated the drag
7349  *
7350  * Starts moving a window. This function is used if an application has
7351  * window movement grips. When GDK can support it, the window movement
7352  * will be done using the standard mechanism for the <link
7353  * linkend="gtk-X11-arch">window manager</link> or windowing
7354  * system. Otherwise, GDK will try to emulate window movement,
7355  * potentially not all that well, depending on the windowing system.
7356  * 
7357  **/
7358 void
7359 gtk_window_begin_move_drag  (GtkWindow *window,
7360                              gint       button,
7361                              gint       root_x,
7362                              gint       root_y,
7363                              guint32    timestamp)
7364 {
7365   GtkWidget *widget;
7366   GdkWindow *toplevel;
7367   
7368   g_return_if_fail (GTK_IS_WINDOW (window));
7369   g_return_if_fail (GTK_WIDGET_VISIBLE (window));
7370   
7371   widget = GTK_WIDGET (window);
7372   
7373   if (window->frame)
7374     toplevel = window->frame;
7375   else
7376     toplevel = widget->window;
7377   
7378   gdk_window_begin_move_drag (toplevel,
7379                               button,
7380                               root_x, root_y,
7381                               timestamp);
7382 }
7383
7384 /** 
7385  * gtk_window_set_screen:
7386  * @window: a #GtkWindow.
7387  * @screen: a #GdkScreen.
7388  *
7389  * Sets the #GdkScreen where the @window is displayed; if
7390  * the window is already mapped, it will be unmapped, and
7391  * then remapped on the new screen.
7392  *
7393  * Since: 2.2
7394  */
7395 void
7396 gtk_window_set_screen (GtkWindow *window,
7397                        GdkScreen *screen)
7398 {
7399   GtkWidget *widget;
7400   GdkScreen *previous_screen;
7401   gboolean was_mapped;
7402   
7403   g_return_if_fail (GTK_IS_WINDOW (window));
7404   g_return_if_fail (GDK_IS_SCREEN (screen));
7405
7406   if (screen == window->screen)
7407     return;
7408
7409   widget = GTK_WIDGET (window);
7410
7411   previous_screen = window->screen;
7412   was_mapped = GTK_WIDGET_MAPPED (widget);
7413
7414   if (was_mapped)
7415     gtk_widget_unmap (widget);
7416   if (GTK_WIDGET_REALIZED (widget))
7417     gtk_widget_unrealize (widget);
7418       
7419   gtk_window_free_key_hash (window);
7420   window->screen = screen;
7421   gtk_widget_reset_rc_styles (widget);
7422   if (screen != previous_screen)
7423     {
7424       g_signal_handlers_disconnect_by_func (previous_screen,
7425                                             gtk_window_on_composited_changed, window);
7426       g_signal_connect (screen, "composited-changed", 
7427                         G_CALLBACK (gtk_window_on_composited_changed), window);
7428       
7429       _gtk_widget_propagate_screen_changed (widget, previous_screen);
7430       _gtk_widget_propagate_composited_changed (widget);
7431     }
7432   g_object_notify (G_OBJECT (window), "screen");
7433
7434   if (was_mapped)
7435     gtk_widget_map (widget);
7436 }
7437
7438 static void
7439 gtk_window_on_composited_changed (GdkScreen *screen,
7440                                   GtkWindow *window)
7441 {
7442   gtk_widget_queue_draw (GTK_WIDGET (window));
7443   
7444   _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
7445 }
7446
7447 static GdkScreen *
7448 gtk_window_check_screen (GtkWindow *window)
7449 {
7450   if (window->screen)
7451     return window->screen;
7452   else
7453     {
7454       g_warning ("Screen for GtkWindow not set; you must always set\n"
7455                  "a screen for a GtkWindow before using the window");
7456       return NULL;
7457     }
7458 }
7459
7460 /** 
7461  * gtk_window_get_screen:
7462  * @window: a #GtkWindow.
7463  *
7464  * Returns the #GdkScreen associated with @window.
7465  *
7466  * Return value: a #GdkScreen.
7467  *
7468  * Since: 2.2
7469  */
7470 GdkScreen*
7471 gtk_window_get_screen (GtkWindow *window)
7472 {
7473   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
7474    
7475   return window->screen;
7476 }
7477
7478 /**
7479  * gtk_window_is_active:
7480  * @window: a #GtkWindow
7481  * 
7482  * Returns whether the window is part of the current active toplevel.
7483  * (That is, the toplevel window receiving keystrokes.)
7484  * The return value is %TRUE if the window is active toplevel
7485  * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
7486  * You might use this function if you wanted to draw a widget
7487  * differently in an active window from a widget in an inactive window.
7488  * See gtk_window_has_toplevel_focus()
7489  * 
7490  * Return value: %TRUE if the window part of the current active window.
7491  *
7492  * Since: 2.4
7493  **/
7494 gboolean
7495 gtk_window_is_active (GtkWindow *window)
7496 {
7497   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7498
7499   return window->is_active;
7500 }
7501
7502 /**
7503  * gtk_window_has_toplevel_focus:
7504  * @window: a #GtkWindow
7505  * 
7506  * Returns whether the input focus is within this GtkWindow.
7507  * For real toplevel windows, this is identical to gtk_window_is_active(),
7508  * but for embedded windows, like #GtkPlug, the results will differ.
7509  * 
7510  * Return value: %TRUE if the input focus is within this GtkWindow
7511  *
7512  * Since: 2.4
7513  **/
7514 gboolean
7515 gtk_window_has_toplevel_focus (GtkWindow *window)
7516 {
7517   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7518
7519   return window->has_toplevel_focus;
7520 }
7521
7522 static void
7523 gtk_window_group_class_init (GtkWindowGroupClass *klass)
7524 {
7525 }
7526
7527 GType
7528 gtk_window_group_get_type (void)
7529 {
7530   static GType window_group_type = 0;
7531
7532   if (!window_group_type)
7533     {
7534       const GTypeInfo window_group_info =
7535       {
7536         sizeof (GtkWindowGroupClass),
7537         NULL,           /* base_init */
7538         NULL,           /* base_finalize */
7539         (GClassInitFunc) gtk_window_group_class_init,
7540         NULL,           /* class_finalize */
7541         NULL,           /* class_data */
7542         sizeof (GtkWindowGroup),
7543         0,              /* n_preallocs */
7544         (GInstanceInitFunc) NULL,
7545       };
7546
7547       window_group_type = g_type_register_static (G_TYPE_OBJECT, I_("GtkWindowGroup"), 
7548                                                   &window_group_info, 0);
7549     }
7550
7551   return window_group_type;
7552 }
7553
7554 /**
7555  * gtk_window_group_new:
7556  * 
7557  * Creates a new #GtkWindowGroup object. Grabs added with
7558  * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
7559  * 
7560  * Return value: a new #GtkWindowGroup. 
7561  **/
7562 GtkWindowGroup *
7563 gtk_window_group_new (void)
7564 {
7565   return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
7566 }
7567
7568 static void
7569 window_group_cleanup_grabs (GtkWindowGroup *group,
7570                             GtkWindow      *window)
7571 {
7572   GSList *tmp_list;
7573   GSList *to_remove = NULL;
7574
7575   tmp_list = group->grabs;
7576   while (tmp_list)
7577     {
7578       if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
7579         to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
7580       tmp_list = tmp_list->next;
7581     }
7582
7583   while (to_remove)
7584     {
7585       gtk_grab_remove (to_remove->data);
7586       g_object_unref (to_remove->data);
7587       to_remove = g_slist_delete_link (to_remove, to_remove);
7588     }
7589 }
7590
7591 /**
7592  * gtk_window_group_add_window:
7593  * @window_group: a #GtkWindowGroup
7594  * @window: the #GtkWindow to add
7595  * 
7596  * Adds a window to a #GtkWindowGroup. 
7597  **/
7598 void
7599 gtk_window_group_add_window (GtkWindowGroup *window_group,
7600                              GtkWindow      *window)
7601 {
7602   g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
7603   g_return_if_fail (GTK_IS_WINDOW (window));
7604
7605   if (window->group != window_group)
7606     {
7607       g_object_ref (window);
7608       g_object_ref (window_group);
7609       
7610       if (window->group)
7611         gtk_window_group_remove_window (window->group, window);
7612       else
7613         window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
7614
7615       window->group = window_group;
7616
7617       g_object_unref (window);
7618     }
7619 }
7620
7621 /**
7622  * gtk_window_group_remove_window:
7623  * @window_group: a #GtkWindowGroup
7624  * @window: the #GtkWindow to remove
7625  * 
7626  * Removes a window from a #GtkWindowGroup.
7627  **/
7628 void
7629 gtk_window_group_remove_window (GtkWindowGroup *window_group,
7630                                 GtkWindow      *window)
7631 {
7632   g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
7633   g_return_if_fail (GTK_IS_WINDOW (window));
7634   g_return_if_fail (window->group == window_group);
7635
7636   g_object_ref (window);
7637
7638   window_group_cleanup_grabs (window_group, window);
7639   window->group = NULL;
7640   
7641   g_object_unref (window_group);
7642   g_object_unref (window);
7643 }
7644
7645 /**
7646  * gtk_window_group_list_windows:
7647  * @window_group: a #GtkWindowGroup
7648  *
7649  * Returns a list of the #GtkWindows that belong to @window_group.
7650  *
7651  * Returns: A newly-allocated list of windows inside the group.
7652  *
7653  * Since: 2.14
7654  **/
7655 GList *
7656 gtk_window_group_list_windows (GtkWindowGroup *window_group)
7657 {
7658   GList *toplevels, *toplevel, *group_windows;
7659
7660   g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
7661
7662   group_windows = NULL;
7663   toplevels = gtk_window_list_toplevels ();
7664
7665   for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
7666     {
7667       GtkWindow *window = toplevel->data;
7668
7669       if (window_group == window->group)
7670         group_windows = g_list_prepend (group_windows, window);
7671     }
7672
7673   return g_list_reverse (group_windows);
7674 }
7675
7676 /**
7677  * gtk_window_get_group:
7678  * @window: a #GtkWindow, or %NULL
7679  *
7680  * Returns the group for @window or the default group, if
7681  * @window is %NULL or if @window does not have an explicit
7682  * window group. 
7683  *
7684  * Returns: the #GtkWindowGroup for a window or the default group
7685  *
7686  * Since: 2.10
7687  */
7688 GtkWindowGroup *
7689 gtk_window_get_group (GtkWindow *window)
7690 {
7691   if (window && window->group)
7692     return window->group;
7693   else
7694     {
7695       static GtkWindowGroup *default_group = NULL;
7696
7697       if (!default_group)
7698         default_group = gtk_window_group_new ();
7699
7700       return default_group;
7701     }
7702 }
7703
7704 /* Return the current grab widget of the given group 
7705  */
7706 GtkWidget *
7707 _gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
7708 {
7709   if (window_group->grabs)
7710     return GTK_WIDGET (window_group->grabs->data);
7711   return NULL;
7712 }
7713
7714 /*
7715   Derived from XParseGeometry() in XFree86  
7716
7717   Copyright 1985, 1986, 1987,1998  The Open Group
7718
7719   All Rights Reserved.
7720
7721   The above copyright notice and this permission notice shall be included
7722   in all copies or substantial portions of the Software.
7723
7724   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
7725   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
7726   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
7727   IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
7728   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
7729   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
7730   OTHER DEALINGS IN THE SOFTWARE.
7731
7732   Except as contained in this notice, the name of The Open Group shall
7733   not be used in advertising or otherwise to promote the sale, use or
7734   other dealings in this Software without prior written authorization
7735   from The Open Group.
7736 */
7737
7738
7739 /*
7740  *    XParseGeometry parses strings of the form
7741  *   "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
7742  *   width, height, xoffset, and yoffset are unsigned integers.
7743  *   Example:  "=80x24+300-49"
7744  *   The equal sign is optional.
7745  *   It returns a bitmask that indicates which of the four values
7746  *   were actually found in the string.  For each value found,
7747  *   the corresponding argument is updated;  for each value
7748  *   not found, the corresponding argument is left unchanged. 
7749  */
7750
7751 /* The following code is from Xlib, and is minimally modified, so we
7752  * can track any upstream changes if required.  Don't change this
7753  * code. Or if you do, put in a huge comment marking which thing
7754  * changed.
7755  */
7756
7757 static int
7758 read_int (gchar   *string,
7759           gchar  **next)
7760 {
7761   int result = 0;
7762   int sign = 1;
7763   
7764   if (*string == '+')
7765     string++;
7766   else if (*string == '-')
7767     {
7768       string++;
7769       sign = -1;
7770     }
7771
7772   for (; (*string >= '0') && (*string <= '9'); string++)
7773     {
7774       result = (result * 10) + (*string - '0');
7775     }
7776
7777   *next = string;
7778
7779   if (sign >= 0)
7780     return (result);
7781   else
7782     return (-result);
7783 }
7784
7785 /* 
7786  * Bitmask returned by XParseGeometry().  Each bit tells if the corresponding
7787  * value (x, y, width, height) was found in the parsed string.
7788  */
7789 #define NoValue         0x0000
7790 #define XValue          0x0001
7791 #define YValue          0x0002
7792 #define WidthValue      0x0004
7793 #define HeightValue     0x0008
7794 #define AllValues       0x000F
7795 #define XNegative       0x0010
7796 #define YNegative       0x0020
7797
7798 /* Try not to reformat/modify, so we can compare/sync with X sources */
7799 static int
7800 gtk_XParseGeometry (const char   *string,
7801                     int          *x,
7802                     int          *y,
7803                     unsigned int *width,   
7804                     unsigned int *height)  
7805 {
7806   int mask = NoValue;
7807   char *strind;
7808   unsigned int tempWidth, tempHeight;
7809   int tempX, tempY;
7810   char *nextCharacter;
7811
7812   /* These initializations are just to silence gcc */
7813   tempWidth = 0;
7814   tempHeight = 0;
7815   tempX = 0;
7816   tempY = 0;
7817   
7818   if ( (string == NULL) || (*string == '\0')) return(mask);
7819   if (*string == '=')
7820     string++;  /* ignore possible '=' at beg of geometry spec */
7821
7822   strind = (char *)string;
7823   if (*strind != '+' && *strind != '-' && *strind != 'x') {
7824     tempWidth = read_int(strind, &nextCharacter);
7825     if (strind == nextCharacter) 
7826       return (0);
7827     strind = nextCharacter;
7828     mask |= WidthValue;
7829   }
7830
7831   if (*strind == 'x' || *strind == 'X') {       
7832     strind++;
7833     tempHeight = read_int(strind, &nextCharacter);
7834     if (strind == nextCharacter)
7835       return (0);
7836     strind = nextCharacter;
7837     mask |= HeightValue;
7838   }
7839
7840   if ((*strind == '+') || (*strind == '-')) {
7841     if (*strind == '-') {
7842       strind++;
7843       tempX = -read_int(strind, &nextCharacter);
7844       if (strind == nextCharacter)
7845         return (0);
7846       strind = nextCharacter;
7847       mask |= XNegative;
7848
7849     }
7850     else
7851       { strind++;
7852       tempX = read_int(strind, &nextCharacter);
7853       if (strind == nextCharacter)
7854         return(0);
7855       strind = nextCharacter;
7856       }
7857     mask |= XValue;
7858     if ((*strind == '+') || (*strind == '-')) {
7859       if (*strind == '-') {
7860         strind++;
7861         tempY = -read_int(strind, &nextCharacter);
7862         if (strind == nextCharacter)
7863           return(0);
7864         strind = nextCharacter;
7865         mask |= YNegative;
7866
7867       }
7868       else
7869         {
7870           strind++;
7871           tempY = read_int(strind, &nextCharacter);
7872           if (strind == nextCharacter)
7873             return(0);
7874           strind = nextCharacter;
7875         }
7876       mask |= YValue;
7877     }
7878   }
7879         
7880   /* If strind isn't at the end of the string the it's an invalid
7881                 geometry specification. */
7882
7883   if (*strind != '\0') return (0);
7884
7885   if (mask & XValue)
7886     *x = tempX;
7887   if (mask & YValue)
7888     *y = tempY;
7889   if (mask & WidthValue)
7890     *width = tempWidth;
7891   if (mask & HeightValue)
7892     *height = tempHeight;
7893   return (mask);
7894 }
7895
7896 /**
7897  * gtk_window_parse_geometry:
7898  * @window: a #GtkWindow
7899  * @geometry: geometry string
7900  * 
7901  * Parses a standard X Window System geometry string - see the
7902  * manual page for X (type 'man X') for details on this.
7903  * gtk_window_parse_geometry() does work on all GTK+ ports
7904  * including Win32 but is primarily intended for an X environment.
7905  *
7906  * If either a size or a position can be extracted from the
7907  * geometry string, gtk_window_parse_geometry() returns %TRUE
7908  * and calls gtk_window_set_default_size() and/or gtk_window_move()
7909  * to resize/move the window.
7910  *
7911  * If gtk_window_parse_geometry() returns %TRUE, it will also
7912  * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
7913  * indicating to the window manager that the size/position of
7914  * the window was user-specified. This causes most window
7915  * managers to honor the geometry.
7916  *
7917  * Note that for gtk_window_parse_geometry() to work as expected, it has
7918  * to be called when the window has its "final" size, i.e. after calling
7919  * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
7920  * on the window.
7921  * |[
7922  * #include <gtk/gtk.h>
7923  *    
7924  * static void
7925  * fill_with_content (GtkWidget *vbox)
7926  * {
7927  *   /&ast; fill with content... &ast;/
7928  * }
7929  *    
7930  * int
7931  * main (int argc, char *argv[])
7932  * {
7933  *   GtkWidget *window, *vbox;
7934  *   GdkGeometry size_hints = {
7935  *     100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST  
7936  *   };
7937  *    
7938  *   gtk_init (&argc, &argv);
7939  *   
7940  *   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7941  *   vbox = gtk_vbox_new (FALSE, 0);
7942  *   
7943  *   gtk_container_add (GTK_CONTAINER (window), vbox);
7944  *   fill_with_content (vbox);
7945  *   gtk_widget_show_all (vbox);
7946  *   
7947  *   gtk_window_set_geometry_hints (GTK_WINDOW (window),
7948  *                                  window,
7949  *                                  &size_hints,
7950  *                                  GDK_HINT_MIN_SIZE | 
7951  *                                  GDK_HINT_BASE_SIZE | 
7952  *                                  GDK_HINT_RESIZE_INC);
7953  *   
7954  *   if (argc &gt; 1)
7955  *     {
7956  *       if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
7957  *         fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
7958  *     }
7959  *    
7960  *   gtk_widget_show_all (window);
7961  *   gtk_main ();
7962  *    
7963  *   return 0;
7964  * }
7965  * ]|
7966  *
7967  * Return value: %TRUE if string was parsed successfully
7968  **/
7969 gboolean
7970 gtk_window_parse_geometry (GtkWindow   *window,
7971                            const gchar *geometry)
7972 {
7973   gint result, x = 0, y = 0;
7974   guint w, h;
7975   GdkGravity grav;
7976   gboolean size_set, pos_set;
7977   GdkScreen *screen;
7978   
7979   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7980   g_return_val_if_fail (geometry != NULL, FALSE);
7981
7982   screen = gtk_window_check_screen (window);
7983   
7984   result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
7985
7986   size_set = FALSE;
7987   if ((result & WidthValue) || (result & HeightValue))
7988     {
7989       gtk_window_set_default_size_internal (window, 
7990                                             TRUE, result & WidthValue ? w : -1,
7991                                             TRUE, result & HeightValue ? h : -1, 
7992                                             TRUE);
7993       size_set = TRUE;
7994     }
7995
7996   gtk_window_get_size (window, (gint *)&w, (gint *)&h);
7997   
7998   grav = GDK_GRAVITY_NORTH_WEST;
7999
8000   if ((result & XNegative) && (result & YNegative))
8001     grav = GDK_GRAVITY_SOUTH_EAST;
8002   else if (result & XNegative)
8003     grav = GDK_GRAVITY_NORTH_EAST;
8004   else if (result & YNegative)
8005     grav = GDK_GRAVITY_SOUTH_WEST;
8006
8007   if ((result & XValue) == 0)
8008     x = 0;
8009
8010   if ((result & YValue) == 0)
8011     y = 0;
8012
8013   if (grav == GDK_GRAVITY_SOUTH_WEST ||
8014       grav == GDK_GRAVITY_SOUTH_EAST)
8015     y = gdk_screen_get_height (screen) - h + y;
8016
8017   if (grav == GDK_GRAVITY_SOUTH_EAST ||
8018       grav == GDK_GRAVITY_NORTH_EAST)
8019     x = gdk_screen_get_width (screen) - w + x;
8020
8021   /* we don't let you put a window offscreen; maybe some people would
8022    * prefer to be able to, but it's kind of a bogus thing to do.
8023    */
8024   if (y < 0)
8025     y = 0;
8026
8027   if (x < 0)
8028     x = 0;
8029
8030   pos_set = FALSE;
8031   if ((result & XValue) || (result & YValue))
8032     {
8033       gtk_window_set_gravity (window, grav);
8034       gtk_window_move (window, x, y);
8035       pos_set = TRUE;
8036     }
8037
8038   if (size_set || pos_set)
8039     {
8040       /* Set USSize, USPosition hints */
8041       GtkWindowGeometryInfo *info;
8042
8043       info = gtk_window_get_geometry_info (window, TRUE);
8044
8045       if (pos_set)
8046         info->mask |= GDK_HINT_USER_POS;
8047       if (size_set)
8048         info->mask |= GDK_HINT_USER_SIZE;
8049     }
8050   
8051   return result != 0;
8052 }
8053
8054 static void
8055 gtk_window_mnemonic_hash_foreach (guint      keyval,
8056                                   GSList    *targets,
8057                                   gpointer   data)
8058 {
8059   struct {
8060     GtkWindow *window;
8061     GtkWindowKeysForeachFunc func;
8062     gpointer func_data;
8063   } *info = data;
8064
8065   (*info->func) (info->window, keyval, info->window->mnemonic_modifier, TRUE, info->func_data);
8066 }
8067
8068 void
8069 _gtk_window_keys_foreach (GtkWindow                *window,
8070                           GtkWindowKeysForeachFunc func,
8071                           gpointer                 func_data)
8072 {
8073   GSList *groups;
8074   GtkMnemonicHash *mnemonic_hash;
8075
8076   struct {
8077     GtkWindow *window;
8078     GtkWindowKeysForeachFunc func;
8079     gpointer func_data;
8080   } info;
8081
8082   info.window = window;
8083   info.func = func;
8084   info.func_data = func_data;
8085
8086   mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
8087   if (mnemonic_hash)
8088     _gtk_mnemonic_hash_foreach (mnemonic_hash,
8089                                 gtk_window_mnemonic_hash_foreach, &info);
8090
8091   groups = gtk_accel_groups_from_object (G_OBJECT (window));
8092   while (groups)
8093     {
8094       GtkAccelGroup *group = groups->data;
8095       gint i;
8096
8097       for (i = 0; i < group->n_accels; i++)
8098         {
8099           GtkAccelKey *key = &group->priv_accels[i].key;
8100           
8101           if (key->accel_key)
8102             (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
8103         }
8104       
8105       groups = groups->next;
8106     }
8107 }
8108
8109 static void
8110 gtk_window_keys_changed (GtkWindow *window)
8111 {
8112   gtk_window_free_key_hash (window);
8113   gtk_window_get_key_hash (window);
8114 }
8115
8116 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
8117
8118 struct _GtkWindowKeyEntry
8119 {
8120   guint keyval;
8121   guint modifiers;
8122   guint is_mnemonic : 1;
8123 };
8124
8125 static void 
8126 window_key_entry_destroy (gpointer data)
8127 {
8128   g_slice_free (GtkWindowKeyEntry, data);
8129 }
8130
8131 static void
8132 add_to_key_hash (GtkWindow      *window,
8133                  guint           keyval,
8134                  GdkModifierType modifiers,
8135                  gboolean        is_mnemonic,
8136                  gpointer        data)
8137 {
8138   GtkKeyHash *key_hash = data;
8139
8140   GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
8141
8142   entry->keyval = keyval;
8143   entry->modifiers = modifiers;
8144   entry->is_mnemonic = is_mnemonic;
8145
8146   /* GtkAccelGroup stores lowercased accelerators. To deal
8147    * with this, if <Shift> was specified, uppercase.
8148    */
8149   if (modifiers & GDK_SHIFT_MASK)
8150     {
8151       if (keyval == GDK_Tab)
8152         keyval = GDK_ISO_Left_Tab;
8153       else
8154         keyval = gdk_keyval_to_upper (keyval);
8155     }
8156   
8157   _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
8158 }
8159
8160 static GtkKeyHash *
8161 gtk_window_get_key_hash (GtkWindow *window)
8162 {
8163   GdkScreen *screen = gtk_window_check_screen (window);
8164   GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
8165   
8166   if (key_hash)
8167     return key_hash;
8168   
8169   key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
8170                                 (GDestroyNotify)window_key_entry_destroy);
8171   _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
8172   g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
8173
8174   return key_hash;
8175 }
8176
8177 static void
8178 gtk_window_free_key_hash (GtkWindow *window)
8179 {
8180   GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
8181   if (key_hash)
8182     {
8183       _gtk_key_hash_free (key_hash);
8184       g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
8185     }
8186 }
8187
8188 /**
8189  * gtk_window_activate_key:
8190  * @window:  a #GtkWindow
8191  * @event:   a #GdkEventKey
8192  *
8193  * Activates mnemonics and accelerators for this #GtkWindow. This is normally
8194  * called by the default ::key_press_event handler for toplevel windows,
8195  * however in some cases it may be useful to call this directly when
8196  * overriding the standard key handling for a toplevel window.
8197  *
8198  * Return value: %TRUE if a mnemonic or accelerator was found and activated.
8199  **/
8200 gboolean
8201 gtk_window_activate_key (GtkWindow   *window,
8202                          GdkEventKey *event)
8203 {
8204   GtkKeyHash *key_hash;
8205   GtkWindowKeyEntry *found_entry = NULL;
8206   gboolean enable_mnemonics;
8207   gboolean enable_accels;
8208
8209   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8210   g_return_val_if_fail (event != NULL, FALSE);
8211
8212   key_hash = gtk_window_get_key_hash (window);
8213
8214   if (key_hash)
8215     {
8216       GSList *tmp_list;
8217       GSList *entries = _gtk_key_hash_lookup (key_hash,
8218                                               event->hardware_keycode,
8219                                               event->state,
8220                                               gtk_accelerator_get_default_mod_mask (),
8221                                               event->group);
8222
8223       g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
8224                     "gtk-enable-mnemonics", &enable_mnemonics,
8225                     "gtk-enable-accels", &enable_accels,
8226                     NULL);
8227
8228       for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
8229         {
8230           GtkWindowKeyEntry *entry = tmp_list->data;
8231           if (entry->is_mnemonic)
8232             {
8233               if (enable_mnemonics)
8234                 {
8235                   found_entry = entry;
8236                   break;
8237                 }
8238             }
8239           else 
8240             {
8241               if (enable_accels && !found_entry)
8242                 {
8243                   found_entry = entry;
8244                 }
8245             }
8246         }
8247
8248       g_slist_free (entries);
8249     }
8250
8251   if (found_entry)
8252     {
8253       if (found_entry->is_mnemonic)
8254         {
8255           if (enable_mnemonics)
8256             return gtk_window_mnemonic_activate (window, found_entry->keyval,
8257                                                  found_entry->modifiers);
8258         }
8259       else
8260         {
8261           if (enable_accels)
8262             return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
8263                                               found_entry->modifiers);
8264         }
8265     }
8266
8267   return FALSE;
8268 }
8269
8270 static void
8271 window_update_has_focus (GtkWindow *window)
8272 {
8273   GtkWidget *widget = GTK_WIDGET (window);
8274   gboolean has_focus = window->has_toplevel_focus && window->is_active;
8275   
8276   if (has_focus != window->has_focus)
8277     {
8278       window->has_focus = has_focus;
8279       
8280       if (has_focus)
8281         {
8282           if (window->focus_widget &&
8283               window->focus_widget != widget &&
8284               !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
8285             do_focus_change (window->focus_widget, TRUE);       
8286         }
8287       else
8288         {
8289           if (window->focus_widget &&
8290               window->focus_widget != widget &&
8291               GTK_WIDGET_HAS_FOCUS (window->focus_widget))
8292             do_focus_change (window->focus_widget, FALSE);
8293         }
8294     }
8295 }
8296
8297 /**
8298  * _gtk_window_set_is_active:
8299  * @window: a #GtkWindow
8300  * @is_active: %TRUE if the window is in the currently active toplevel
8301  * 
8302  * Internal function that sets whether the #GtkWindow is part
8303  * of the currently active toplevel window (taking into account inter-process
8304  * embedding.)
8305  **/
8306 void
8307 _gtk_window_set_is_active (GtkWindow *window,
8308                            gboolean   is_active)
8309 {
8310   g_return_if_fail (GTK_IS_WINDOW (window));
8311
8312   is_active = is_active != FALSE;
8313
8314   if (is_active != window->is_active)
8315     {
8316       window->is_active = is_active;
8317       window_update_has_focus (window);
8318
8319       g_object_notify (G_OBJECT (window), "is-active");
8320     }
8321 }
8322
8323 /**
8324  * _gtk_windwo_set_is_toplevel:
8325  * @window: a #GtkWindow
8326  * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
8327  * parent of the root window); %FALSE if it is not (for example, for an
8328  * in-process, parented GtkPlug)
8329  *
8330  * Internal function used by #GtkPlug when it gets parented/unparented by a
8331  * #GtkSocket.  This keeps the @window's #GTK_TOPLEVEL flag in sync with the
8332  * global list of toplevel windows.
8333  */
8334 void
8335 _gtk_window_set_is_toplevel (GtkWindow *window,
8336                              gboolean   is_toplevel)
8337 {
8338   if (GTK_WIDGET_TOPLEVEL (window))
8339     g_assert (g_slist_find (toplevel_list, window) != NULL);
8340   else
8341     g_assert (g_slist_find (toplevel_list, window) == NULL);
8342
8343   if (is_toplevel == GTK_WIDGET_TOPLEVEL (window))
8344     return;
8345
8346   if (is_toplevel)
8347     {
8348       GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
8349       toplevel_list = g_slist_prepend (toplevel_list, window);
8350     }
8351   else
8352     {
8353       GTK_WIDGET_UNSET_FLAGS (window, GTK_TOPLEVEL);
8354       toplevel_list = g_slist_remove (toplevel_list, window);
8355     }
8356 }
8357
8358 /**
8359  * _gtk_window_set_has_toplevel_focus:
8360  * @window: a #GtkWindow
8361  * @has_toplevel_focus: %TRUE if the in
8362  * 
8363  * Internal function that sets whether the keyboard focus for the
8364  * toplevel window (taking into account inter-process embedding.)
8365  **/
8366 void
8367 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
8368                                    gboolean   has_toplevel_focus)
8369 {
8370   g_return_if_fail (GTK_IS_WINDOW (window));
8371   
8372   has_toplevel_focus = has_toplevel_focus != FALSE;
8373
8374   if (has_toplevel_focus != window->has_toplevel_focus)
8375     {
8376       window->has_toplevel_focus = has_toplevel_focus;
8377       window_update_has_focus (window);
8378
8379       g_object_notify (G_OBJECT (window), "has-toplevel-focus");
8380     }
8381 }
8382
8383 /**
8384  * gtk_window_set_auto_startup_notification:
8385  * @setting: %TRUE to automatically do startup notification
8386  *
8387  * By default, after showing the first #GtkWindow, GTK+ calls 
8388  * gdk_notify_startup_complete().  Call this function to disable 
8389  * the automatic startup notification. You might do this if your 
8390  * first window is a splash screen, and you want to delay notification 
8391  * until after your real main window has been shown, for example.
8392  *
8393  * In that example, you would disable startup notification
8394  * temporarily, show your splash screen, then re-enable it so that
8395  * showing the main window would automatically result in notification.
8396  * 
8397  * Since: 2.2
8398  **/
8399 void
8400 gtk_window_set_auto_startup_notification (gboolean setting)
8401 {
8402   disable_startup_notification = !setting;
8403 }
8404
8405 #if defined (G_OS_WIN32) && !defined (_WIN64)
8406
8407 #undef gtk_window_set_icon_from_file
8408
8409 gboolean
8410 gtk_window_set_icon_from_file (GtkWindow   *window,
8411                                const gchar *filename,
8412                                GError     **err)
8413 {
8414   gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, err);
8415   gboolean retval;
8416
8417   if (utf8_filename == NULL)
8418     return FALSE;
8419
8420   retval = gtk_window_set_icon_from_file_utf8 (window, utf8_filename, err);
8421
8422   g_free (utf8_filename);
8423
8424   return retval;
8425 }
8426
8427 #undef gtk_window_set_default_icon_from_file
8428
8429 gboolean
8430 gtk_window_set_default_icon_from_file (const gchar *filename,
8431                                        GError     **err)
8432 {
8433   gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, err);
8434   gboolean retval;
8435
8436   if (utf8_filename == NULL)
8437     return FALSE;
8438
8439   retval = gtk_window_set_default_icon_from_file_utf8 (utf8_filename, err);
8440
8441   g_free (utf8_filename);
8442
8443   return retval;
8444 }
8445
8446 #endif
8447
8448 #define __GTK_WINDOW_C__
8449 #include "gtkaliasdef.c"