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