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