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