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