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