]> Pileus Git - ~andy/gtk/blob - gtk/gtkwindow.c
c21e0d396323540addd58cb018e4961a8606a732
[~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   toplevel_list = g_slist_remove (toplevel_list, window);
4517
4518   if (priv->transient_parent)
4519     gtk_window_set_transient_for (window, NULL);
4520
4521   /* frees the icons */
4522   gtk_window_set_icon_list (window, NULL);
4523   
4524   if (priv->has_user_ref_count)
4525     {
4526       priv->has_user_ref_count = FALSE;
4527       g_object_unref (window);
4528     }
4529
4530   if (priv->group)
4531     gtk_window_group_remove_window (priv->group, window);
4532
4533    gtk_window_free_key_hash (window);
4534
4535   GTK_WIDGET_CLASS (gtk_window_parent_class)->destroy (widget);
4536 }
4537
4538 static void
4539 gtk_window_finalize (GObject *object)
4540 {
4541   GtkWindow *window = GTK_WINDOW (object);
4542   GtkWindowPrivate *priv = window->priv;
4543   GtkMnemonicHash *mnemonic_hash;
4544
4545   g_free (priv->title);
4546   g_free (priv->wmclass_name);
4547   g_free (priv->wmclass_class);
4548   g_free (priv->wm_role);
4549   gtk_window_release_application (window);
4550
4551   mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4552   if (mnemonic_hash)
4553     _gtk_mnemonic_hash_free (mnemonic_hash);
4554
4555   if (priv->geometry_info)
4556     {
4557       if (priv->geometry_info->widget)
4558         g_signal_handlers_disconnect_by_func (priv->geometry_info->widget,
4559                                               gtk_widget_destroyed,
4560                                               &priv->geometry_info->widget);
4561       g_free (priv->geometry_info);
4562     }
4563
4564   if (priv->keys_changed_handler)
4565     {
4566       g_source_remove (priv->keys_changed_handler);
4567       priv->keys_changed_handler = 0;
4568     }
4569
4570   if (priv->screen)
4571     g_signal_handlers_disconnect_by_func (priv->screen,
4572                                           gtk_window_on_composited_changed, window);
4573
4574   g_free (priv->startup_id);
4575
4576   G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4577 }
4578
4579 static void
4580 gtk_window_show (GtkWidget *widget)
4581 {
4582   GtkWindow *window = GTK_WINDOW (widget);
4583   GtkWindowPrivate *priv = window->priv;
4584   GtkContainer *container = GTK_CONTAINER (window);
4585   gboolean need_resize;
4586
4587   _gtk_widget_set_visible_flag (widget, TRUE);
4588
4589   need_resize = _gtk_container_get_need_resize (container) || !gtk_widget_get_realized (widget);
4590   _gtk_container_set_need_resize (container, FALSE);
4591
4592   if (need_resize)
4593     {
4594       GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4595       GtkAllocation allocation = { 0, 0 };
4596       GdkRectangle configure_request;
4597       GdkGeometry new_geometry;
4598       guint new_flags;
4599       gboolean was_realized;
4600
4601       /* We are going to go ahead and perform this configure request
4602        * and then emulate a configure notify by going ahead and
4603        * doing a size allocate. Sort of a synchronous
4604        * mini-copy of gtk_window_move_resize() here.
4605        */
4606       gtk_window_compute_configure_request (window,
4607                                             &configure_request,
4608                                             &new_geometry,
4609                                             &new_flags);
4610       
4611       /* We update this because we are going to go ahead
4612        * and gdk_window_resize() below, rather than
4613        * queuing it.
4614        */
4615       info->last.configure_request.width = configure_request.width;
4616       info->last.configure_request.height = configure_request.height;
4617       
4618       /* and allocate the window - this is normally done
4619        * in move_resize in response to configure notify
4620        */
4621       allocation.width  = configure_request.width;
4622       allocation.height = configure_request.height;
4623       gtk_widget_size_allocate (widget, &allocation);
4624
4625       /* Then we guarantee we have a realize */
4626       was_realized = FALSE;
4627       if (!gtk_widget_get_realized (widget))
4628         {
4629           gtk_widget_realize (widget);
4630           was_realized = TRUE;
4631         }
4632
4633       /* We only send configure request if we didn't just finish
4634        * creating the window; if we just created the window
4635        * then we created it with widget->allocation anyhow.
4636        */
4637       if (!was_realized)
4638         gdk_window_move_resize (gtk_widget_get_window (widget),
4639                                 configure_request.x,
4640                                 configure_request.y,
4641                                 configure_request.width,
4642                                 configure_request.height);
4643     }
4644   
4645   gtk_container_check_resize (container);
4646
4647   gtk_widget_map (widget);
4648
4649   /* Try to make sure that we have some focused widget
4650    */
4651   if (!priv->focus_widget && !GTK_IS_PLUG (window))
4652     gtk_window_move_focus (widget, GTK_DIR_TAB_FORWARD);
4653   
4654   if (priv->modal)
4655     gtk_grab_add (widget);
4656 }
4657
4658 static void
4659 gtk_window_hide (GtkWidget *widget)
4660 {
4661   GtkWindow *window = GTK_WINDOW (widget);
4662   GtkWindowPrivate *priv = window->priv;
4663
4664   _gtk_widget_set_visible_flag (widget, FALSE);
4665   gtk_widget_unmap (widget);
4666
4667   if (priv->modal)
4668     gtk_grab_remove (widget);
4669 }
4670
4671 static void
4672 gtk_window_map (GtkWidget *widget)
4673 {
4674   GtkWidget *child;
4675   GtkWindow *window = GTK_WINDOW (widget);
4676   GtkWindowPrivate *priv = window->priv;
4677   GdkWindow *toplevel;
4678   GdkWindow *gdk_window;
4679   gboolean auto_mnemonics;
4680
4681   gdk_window = gtk_widget_get_window (widget);
4682
4683   gtk_widget_set_mapped (widget, TRUE);
4684
4685   child = gtk_bin_get_child (&(window->bin));
4686   if (child &&
4687       gtk_widget_get_visible (child) &&
4688       !gtk_widget_get_mapped (child))
4689     gtk_widget_map (child);
4690
4691   toplevel = gdk_window;
4692
4693   if (priv->maximize_initially)
4694     gdk_window_maximize (toplevel);
4695   else
4696     gdk_window_unmaximize (toplevel);
4697   
4698   if (priv->stick_initially)
4699     gdk_window_stick (toplevel);
4700   else
4701     gdk_window_unstick (toplevel);
4702   
4703   if (priv->iconify_initially)
4704     gdk_window_iconify (toplevel);
4705   else
4706     gdk_window_deiconify (toplevel);
4707
4708   if (priv->fullscreen_initially)
4709     gdk_window_fullscreen (toplevel);
4710   else
4711     gdk_window_unfullscreen (toplevel);
4712   
4713   gdk_window_set_keep_above (toplevel, priv->above_initially);
4714
4715   gdk_window_set_keep_below (toplevel, priv->below_initially);
4716
4717   /* No longer use the default settings */
4718   priv->need_default_size = FALSE;
4719   priv->need_default_position = FALSE;
4720   
4721   if (priv->reset_type_hint)
4722     {
4723       /* We should only reset the type hint when the application
4724        * used gtk_window_set_type_hint() to change the hint.
4725        * Some applications use X directly to change the properties;
4726        * in that case, we shouldn't overwrite what they did.
4727        */
4728       gdk_window_set_type_hint (gdk_window, priv->type_hint);
4729       priv->reset_type_hint = FALSE;
4730     }
4731
4732   gdk_window_show (gdk_window);
4733
4734   if (priv->grip_window)
4735     gdk_window_show (priv->grip_window);
4736
4737   if (!disable_startup_notification)
4738     {
4739       /* Do we have a custom startup-notification id? */
4740       if (priv->startup_id != NULL)
4741         {
4742           /* Make sure we have a "real" id */
4743           if (!startup_id_is_fake (priv->startup_id)) 
4744             gdk_notify_startup_complete_with_id (priv->startup_id);
4745
4746           g_free (priv->startup_id);
4747           priv->startup_id = NULL;
4748         }
4749       else if (!sent_startup_notification)
4750         {
4751           sent_startup_notification = TRUE;
4752           gdk_notify_startup_complete ();
4753         }
4754     }
4755
4756   /* if auto-mnemonics is enabled and mnemonics visible is not already set
4757    * (as in the case of popup menus), then hide mnemonics initially
4758    */
4759   g_object_get (gtk_widget_get_settings (widget), "gtk-auto-mnemonics",
4760                 &auto_mnemonics, NULL);
4761   if (auto_mnemonics && !priv->mnemonics_visible_set)
4762     gtk_window_set_mnemonics_visible (window, FALSE);
4763 }
4764
4765 static gboolean
4766 gtk_window_map_event (GtkWidget   *widget,
4767                       GdkEventAny *event)
4768 {
4769   if (!gtk_widget_get_mapped (widget))
4770     {
4771       /* we should be be unmapped, but are getting a MapEvent, this may happen
4772        * to toplevel XWindows if mapping was intercepted by a window manager
4773        * and an unmap request occoured while the MapRequestEvent was still
4774        * being handled. we work around this situaiton here by re-requesting
4775        * the window being unmapped. more details can be found in:
4776        *   http://bugzilla.gnome.org/show_bug.cgi?id=316180
4777        */
4778       gdk_window_hide (gtk_widget_get_window (widget));
4779     }
4780   return FALSE;
4781 }
4782
4783 static void
4784 gtk_window_unmap (GtkWidget *widget)
4785 {
4786   GtkWindow *window = GTK_WINDOW (widget);
4787   GtkWindowPrivate *priv = window->priv;
4788   GtkWidget *child;
4789   GtkWindowGeometryInfo *info;
4790   GdkWindow *gdk_window;
4791   GdkWindowState state;
4792
4793   gdk_window = gtk_widget_get_window (widget);
4794
4795   gtk_widget_set_mapped (widget, FALSE);
4796   gdk_window_withdraw (gdk_window);
4797
4798   priv->configure_request_count = 0;
4799   priv->configure_notify_received = FALSE;
4800
4801   /* on unmap, we reset the default positioning of the window,
4802    * so it's placed again, but we don't reset the default
4803    * size of the window, so it's remembered.
4804    */
4805   priv->need_default_position = TRUE;
4806
4807   info = gtk_window_get_geometry_info (window, FALSE);
4808   if (info)
4809     {
4810       info->initial_pos_set = FALSE;
4811       info->position_constraints_changed = FALSE;
4812     }
4813
4814   state = gdk_window_get_state (gdk_window);
4815   priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4816   priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4817   priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4818   priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4819   priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4820
4821   child = gtk_bin_get_child (&(window->bin));
4822   if (child)
4823     gtk_widget_unmap (child);
4824 }
4825
4826 static void
4827 gtk_window_realize (GtkWidget *widget)
4828 {
4829   GtkAllocation allocation;
4830   GtkWindow *window;
4831   GdkWindow *parent_window;
4832   GdkWindow *gdk_window;
4833   GdkWindowAttr attributes;
4834   gint attributes_mask;
4835   GtkWindowPrivate *priv;
4836   GtkStyleContext *context;
4837
4838   window = GTK_WINDOW (widget);
4839   priv = window->priv;
4840
4841   gtk_widget_get_allocation (widget, &allocation);
4842
4843   /* ensure widget tree is properly size allocated */
4844   if (allocation.x == -1 &&
4845       allocation.y == -1 &&
4846       allocation.width == 1 &&
4847       allocation.height == 1)
4848     {
4849       GtkRequisition requisition;
4850
4851       allocation.x = 0;
4852       allocation.y = 0;
4853       allocation.width = 200;
4854       allocation.height = 200;
4855
4856       gtk_widget_get_preferred_size (widget, &requisition, NULL);
4857       if (requisition.width || requisition.height)
4858         {
4859           /* non-empty window */
4860           allocation.width = requisition.width;
4861           allocation.height = requisition.height;
4862         }
4863       gtk_widget_size_allocate (widget, &allocation);
4864       
4865       _gtk_container_queue_resize (GTK_CONTAINER (widget));
4866
4867       g_return_if_fail (!gtk_widget_get_realized (widget));
4868     }
4869   
4870   gtk_widget_set_realized (widget, TRUE);
4871   
4872   switch (priv->type)
4873     {
4874     case GTK_WINDOW_TOPLEVEL:
4875       attributes.window_type = GDK_WINDOW_TOPLEVEL;
4876       break;
4877     case GTK_WINDOW_POPUP:
4878       attributes.window_type = GDK_WINDOW_TEMP;
4879       break;
4880     default:
4881       g_warning (G_STRLOC": Unknown window type %d!", priv->type);
4882       break;
4883     }
4884
4885   attributes.title = priv->title;
4886   attributes.wmclass_name = priv->wmclass_name;
4887   attributes.wmclass_class = priv->wmclass_class;
4888   attributes.wclass = GDK_INPUT_OUTPUT;
4889   attributes.visual = gtk_widget_get_visual (widget);
4890
4891   attributes_mask = 0;
4892   parent_window = gtk_widget_get_root_window (widget);
4893
4894   gtk_widget_get_allocation (widget, &allocation);
4895   attributes.width = allocation.width;
4896   attributes.height = allocation.height;
4897   attributes.event_mask = gtk_widget_get_events (widget);
4898   attributes.event_mask |= (GDK_EXPOSURE_MASK |
4899                             GDK_KEY_PRESS_MASK |
4900                             GDK_KEY_RELEASE_MASK |
4901                             GDK_ENTER_NOTIFY_MASK |
4902                             GDK_LEAVE_NOTIFY_MASK |
4903                             GDK_FOCUS_CHANGE_MASK |
4904                             GDK_STRUCTURE_MASK);
4905   attributes.type_hint = priv->type_hint;
4906
4907   attributes_mask |= GDK_WA_VISUAL | GDK_WA_TYPE_HINT;
4908   attributes_mask |= (priv->title ? GDK_WA_TITLE : 0);
4909   attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0);
4910
4911   gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask);
4912   gtk_widget_set_window (widget, gdk_window);
4913
4914   if (priv->opacity_set)
4915     gdk_window_set_opacity (gdk_window, priv->opacity);
4916
4917   gdk_window_enable_synchronized_configure (gdk_window);
4918
4919   gdk_window_set_user_data (gdk_window, window);
4920
4921   gtk_widget_style_attach (widget);
4922   context = gtk_widget_get_style_context (widget);
4923
4924   gtk_style_context_set_background (context, gdk_window);
4925
4926   if (priv->transient_parent &&
4927       gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
4928     gdk_window_set_transient_for (gdk_window,
4929                                   gtk_widget_get_window (GTK_WIDGET (priv->transient_parent)));
4930
4931   if (priv->wm_role)
4932     gdk_window_set_role (gdk_window, priv->wm_role);
4933
4934   if (!priv->decorated)
4935     gdk_window_set_decorations (gdk_window, 0);
4936
4937   if (!priv->deletable)
4938     gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
4939
4940   if (gtk_window_get_skip_pager_hint (window))
4941     gdk_window_set_skip_pager_hint (gdk_window, TRUE);
4942
4943   if (gtk_window_get_skip_taskbar_hint (window))
4944     gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
4945
4946   if (gtk_window_get_accept_focus (window))
4947     gdk_window_set_accept_focus (gdk_window, TRUE);
4948   else
4949     gdk_window_set_accept_focus (gdk_window, FALSE);
4950
4951   if (gtk_window_get_focus_on_map (window))
4952     gdk_window_set_focus_on_map (gdk_window, TRUE);
4953   else
4954     gdk_window_set_focus_on_map (gdk_window, FALSE);
4955
4956   if (priv->modal)
4957     gdk_window_set_modal_hint (gdk_window, TRUE);
4958   else
4959     gdk_window_set_modal_hint (gdk_window, FALSE);
4960
4961   if (priv->startup_id)
4962     {
4963 #ifdef GDK_WINDOWING_X11
4964       guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
4965       if (timestamp != GDK_CURRENT_TIME)
4966         gdk_x11_window_set_user_time (gdk_window, timestamp);
4967 #endif
4968       if (!startup_id_is_fake (priv->startup_id)) 
4969         gdk_window_set_startup_id (gdk_window, priv->startup_id);
4970     }
4971
4972   /* Icons */
4973   gtk_window_realize_icon (window);
4974
4975   if (priv->has_resize_grip)
4976     resize_grip_create_window (window);
4977 }
4978
4979 static void
4980 gtk_window_unrealize (GtkWidget *widget)
4981 {
4982   GtkWindow *window = GTK_WINDOW (widget);
4983   GtkWindowPrivate *priv = window->priv;
4984   GtkWindowGeometryInfo *info;
4985
4986   /* On unrealize, we reset the size of the window such
4987    * that we will re-apply the default sizing stuff
4988    * next time we show the window.
4989    *
4990    * Default positioning is reset on unmap, instead of unrealize.
4991    */
4992   priv->need_default_size = TRUE;
4993   info = gtk_window_get_geometry_info (window, FALSE);
4994   if (info)
4995     {
4996       info->resize_width = -1;
4997       info->resize_height = -1;
4998       info->last.configure_request.x = 0;
4999       info->last.configure_request.y = 0;
5000       info->last.configure_request.width = -1;
5001       info->last.configure_request.height = -1;
5002       /* be sure we reset geom hints on re-realize */
5003       info->last.flags = 0;
5004     }
5005
5006   /* Icons */
5007   gtk_window_unrealize_icon (window);
5008
5009   if (priv->grip_window != NULL)
5010     resize_grip_destroy_window (window);
5011
5012   GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
5013 }
5014
5015 static GtkJunctionSides
5016 get_grip_junction (GtkWidget *widget)
5017 {
5018   if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5019     return GTK_JUNCTION_CORNER_BOTTOMRIGHT;
5020   else
5021     return GTK_JUNCTION_CORNER_BOTTOMLEFT;
5022 }
5023
5024 static gboolean
5025 get_drag_edge (GtkWidget     *widget,
5026                GdkWindowEdge *edge)
5027 {
5028   GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5029   gboolean hresizable;
5030   gboolean vresizable;
5031   GtkTextDirection dir;
5032   GtkWindowGeometryInfo *info;
5033
5034   hresizable = TRUE;
5035   vresizable = TRUE;
5036
5037   info = priv->geometry_info;
5038   if (info)
5039     {
5040       GdkWindowHints flags = info->last.flags;
5041       GdkGeometry *geometry = &info->last.geometry;
5042
5043       if ((flags & GDK_HINT_MIN_SIZE) && (flags & GDK_HINT_MAX_SIZE))
5044         {
5045           hresizable = geometry->min_width < geometry->max_width;
5046           vresizable = geometry->min_height < geometry->max_height;
5047         }
5048     }
5049
5050   dir = gtk_widget_get_direction (widget);
5051
5052   if (hresizable && vresizable)
5053     *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_SOUTH_EAST : GDK_WINDOW_EDGE_SOUTH_WEST;
5054   else if (hresizable)
5055     *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_EAST : GDK_WINDOW_EDGE_WEST;
5056   else if (vresizable)
5057     *edge = GDK_WINDOW_EDGE_SOUTH;
5058   else
5059     return FALSE;
5060
5061   return TRUE;
5062 }
5063
5064 static void
5065 set_grip_cursor (GtkWindow *window)
5066 {
5067   GtkWidget *widget = GTK_WIDGET (window);
5068   GtkWindowPrivate *priv = window->priv;
5069
5070   if (priv->grip_window == NULL)
5071     return;
5072
5073   if (gtk_widget_is_sensitive (widget))
5074     {
5075       GdkWindowEdge edge;
5076       GdkDisplay *display;
5077       GdkCursorType cursor_type;
5078       GdkCursor *cursor;
5079
5080       cursor_type = GDK_LEFT_PTR;
5081
5082       if (get_drag_edge (widget, &edge))
5083         {
5084           switch (edge)
5085             {
5086             case GDK_WINDOW_EDGE_EAST:
5087               cursor_type = GDK_RIGHT_SIDE;
5088               break;
5089             case GDK_WINDOW_EDGE_SOUTH_EAST:
5090               cursor_type = GDK_BOTTOM_RIGHT_CORNER;
5091               break;
5092             case GDK_WINDOW_EDGE_SOUTH:
5093               cursor_type = GDK_BOTTOM_SIDE;
5094               break;
5095             case GDK_WINDOW_EDGE_SOUTH_WEST:
5096               cursor_type = GDK_BOTTOM_LEFT_CORNER;
5097               break;
5098             case GDK_WINDOW_EDGE_WEST:
5099               cursor_type = GDK_LEFT_SIDE;
5100               break;
5101             default: ;
5102             }
5103         }
5104
5105       display = gtk_widget_get_display (widget);
5106       cursor = gdk_cursor_new_for_display (display, cursor_type);
5107       gdk_window_set_cursor (priv->grip_window, cursor);
5108       g_object_unref (cursor);
5109     }
5110   else
5111     gdk_window_set_cursor (priv->grip_window, NULL);
5112 }
5113
5114 static void
5115 set_grip_shape (GtkWindow *window)
5116 {
5117   GtkWindowPrivate *priv = window->priv;
5118   cairo_region_t *region;
5119   cairo_surface_t *surface;
5120   cairo_t *cr;
5121   double width, height;
5122
5123   if (priv->grip_window == NULL)
5124     return;
5125
5126   width = gdk_window_get_width (priv->grip_window);
5127   height = gdk_window_get_height (priv->grip_window);
5128   surface = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
5129
5130   cr = cairo_create (surface);
5131   cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
5132   cairo_paint (cr);
5133   cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
5134   if (get_grip_junction (GTK_WIDGET (window)) & GTK_JUNCTION_CORNER_BOTTOMRIGHT)
5135     {
5136       cairo_move_to (cr, width, 0.0);
5137       cairo_line_to (cr, width, height);
5138       cairo_line_to (cr, 0.0, height);
5139     }
5140   else
5141     {
5142       cairo_move_to (cr, 0.0, 0.0);
5143       cairo_line_to (cr, width, height);
5144       cairo_line_to (cr, 0.0, height);
5145     }
5146   cairo_close_path (cr);
5147   cairo_fill (cr);
5148   cairo_destroy (cr);
5149   region = gdk_cairo_region_create_from_surface (surface);
5150   cairo_surface_destroy (surface);
5151
5152   gdk_window_shape_combine_region (priv->grip_window, region, 0, 0);
5153   cairo_region_destroy (region);
5154 }
5155
5156 static void
5157 set_grip_position (GtkWindow *window)
5158 {
5159   GtkWindowPrivate *priv = window->priv;
5160   GdkRectangle rect;
5161
5162   if (priv->grip_window == NULL)
5163     return;
5164
5165   gtk_window_get_resize_grip_area (window, &rect);
5166   gdk_window_raise (priv->grip_window);
5167   gdk_window_move_resize (priv->grip_window,
5168                           rect.x, rect.y,
5169                           rect.width, rect.height);
5170 }
5171
5172 static void
5173 gtk_window_size_allocate (GtkWidget     *widget,
5174                           GtkAllocation *allocation)
5175 {
5176   GtkWindow *window = GTK_WINDOW (widget);
5177   GtkAllocation child_allocation;
5178   GtkWidget *child;
5179   guint border_width;
5180
5181   gtk_widget_set_allocation (widget, allocation);
5182
5183   child = gtk_bin_get_child (&(window->bin));
5184   if (child && gtk_widget_get_visible (child))
5185     {
5186       border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
5187       child_allocation.x = border_width;
5188       child_allocation.y = border_width;
5189       child_allocation.width =
5190         MAX (1, (gint)allocation->width - child_allocation.x * 2);
5191       child_allocation.height =
5192         MAX (1, (gint)allocation->height - child_allocation.y * 2);
5193
5194       gtk_widget_size_allocate (child, &child_allocation);
5195     }
5196
5197   if (gtk_widget_get_realized (widget))
5198     {
5199       update_grip_visibility (window);
5200       set_grip_position (window);
5201     }
5202 }
5203
5204 static gint
5205 gtk_window_configure_event (GtkWidget         *widget,
5206                             GdkEventConfigure *event)
5207 {
5208   GtkAllocation allocation;
5209   GtkWindow *window = GTK_WINDOW (widget);
5210   GtkWindowPrivate *priv = window->priv;
5211   gboolean expected_reply = priv->configure_request_count > 0;
5212
5213   /* priv->configure_request_count incremented for each
5214    * configure request, and decremented to a min of 0 for
5215    * each configure notify.
5216    *
5217    * All it means is that we know we will get at least
5218    * priv->configure_request_count more configure notifies.
5219    * We could get more configure notifies than that; some
5220    * of the configure notifies we get may be unrelated to
5221    * the configure requests. But we will get at least
5222    * priv->configure_request_count notifies.
5223    */
5224
5225   if (priv->configure_request_count > 0)
5226     {
5227       priv->configure_request_count -= 1;
5228       gdk_window_thaw_toplevel_updates_libgtk_only (gtk_widget_get_window (widget));
5229     }
5230   
5231   /* As an optimization, we avoid a resize when possible.
5232    *
5233    * The only times we can avoid a resize are:
5234    *   - we know only the position changed, not the size
5235    *   - we know we have made more requests and so will get more
5236    *     notifies and can wait to resize when we get them
5237    */
5238   gtk_widget_get_allocation (widget, &allocation);
5239   if (!expected_reply &&
5240       (allocation.width == event->width &&
5241        allocation.height == event->height))
5242     {
5243       gdk_window_configure_finished (gtk_widget_get_window (widget));
5244       return TRUE;
5245     }
5246
5247   /*
5248    * If we do need to resize, we do that by:
5249    *   - filling in widget->allocation with the new size
5250    *   - setting configure_notify_received to TRUE
5251    *     for use in gtk_window_move_resize()
5252    *   - queueing a resize, leading to invocation of
5253    *     gtk_window_move_resize() in an idle handler
5254    *
5255    */
5256   
5257   priv->configure_notify_received = TRUE;
5258
5259   allocation.width = event->width;
5260   allocation.height = event->height;
5261   gtk_widget_set_allocation (widget, &allocation);
5262
5263   gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again?
5264
5265   _gtk_container_queue_resize (GTK_CONTAINER (widget));
5266   
5267   return TRUE;
5268 }
5269
5270 static gboolean
5271 gtk_window_state_event (GtkWidget           *widget,
5272                         GdkEventWindowState *event)
5273 {
5274   update_grip_visibility (GTK_WINDOW (widget));
5275
5276   return FALSE;
5277 }
5278
5279 static void
5280 gtk_window_direction_changed (GtkWidget        *widget,
5281                               GtkTextDirection  prev_dir)
5282 {
5283   GtkWindow *window = GTK_WINDOW (widget);
5284
5285   set_grip_cursor (window);
5286   set_grip_position (window);
5287   set_grip_shape (window);
5288 }
5289
5290 static void
5291 gtk_window_state_changed (GtkWidget    *widget,
5292                           GtkStateType  previous_state)
5293 {
5294   GtkWindow *window = GTK_WINDOW (widget);
5295
5296   update_grip_visibility (window);
5297 }
5298
5299 static void
5300 gtk_window_style_updated (GtkWidget *widget)
5301 {
5302   GtkWindow *window = GTK_WINDOW (widget);
5303   GtkWindowPrivate *priv = window->priv;
5304   GdkRectangle rect;
5305
5306   if (priv->grip_window != NULL && gtk_window_get_resize_grip_area (window, &rect))
5307     {
5308       gdk_window_move_resize (priv->grip_window,
5309                               rect.x, rect.y,
5310                               rect.width, rect.height);
5311
5312       set_grip_shape (window);
5313       gtk_widget_queue_resize (widget);
5314     }
5315 }
5316
5317 static void
5318 resize_grip_create_window (GtkWindow *window)
5319 {
5320   GtkWidget *widget;
5321   GtkWindowPrivate *priv;
5322   GdkWindowAttr attributes;
5323   gint attributes_mask;
5324   GdkRectangle rect;
5325
5326   priv = window->priv;
5327   widget = GTK_WIDGET (window);
5328
5329   g_return_if_fail (gtk_widget_get_realized (widget));
5330   g_return_if_fail (priv->grip_window == NULL);
5331
5332   gtk_window_get_resize_grip_area (window, &rect);
5333
5334   attributes.x = rect.x;
5335   attributes.y = rect.y;
5336   attributes.width = rect.width;
5337   attributes.height = rect.height;
5338   attributes.window_type = GDK_WINDOW_CHILD;
5339   attributes.wclass = GDK_INPUT_OUTPUT;
5340   attributes.event_mask = gtk_widget_get_events (widget) |
5341                           GDK_EXPOSURE_MASK |
5342                           GDK_BUTTON_PRESS_MASK;
5343
5344   attributes_mask = GDK_WA_X | GDK_WA_Y;
5345
5346   priv->grip_window = gdk_window_new (gtk_widget_get_window (widget),
5347                                       &attributes,
5348                                       attributes_mask);
5349
5350   gdk_window_set_user_data (priv->grip_window, widget);
5351
5352   gdk_window_raise (priv->grip_window);
5353
5354   set_grip_shape (window);
5355   update_grip_visibility (window);
5356 }
5357
5358 static void
5359 resize_grip_destroy_window (GtkWindow *window)
5360 {
5361   GtkWindowPrivate *priv = window->priv;
5362
5363   gdk_window_set_user_data (priv->grip_window, NULL);
5364   gdk_window_destroy (priv->grip_window);
5365   priv->grip_window = NULL;
5366   update_grip_visibility (window);
5367 }
5368
5369 /**
5370  * gtk_window_set_has_resize_grip:
5371  * @window: a #GtkWindow
5372  * @value: %TRUE to allow a resize grip
5373  *
5374  * Sets whether @window has a corner resize grip.
5375  *
5376  * Note that the resize grip is only shown if the window
5377  * is actually resizable and not maximized. Use
5378  * gtk_window_resize_grip_is_visible() to find out if the
5379  * resize grip is currently shown.
5380  *
5381  * Since: 3.0
5382  */
5383 void
5384 gtk_window_set_has_resize_grip (GtkWindow *window,
5385                                 gboolean   value)
5386 {
5387   GtkWidget *widget = GTK_WIDGET (window);
5388   GtkWindowPrivate *priv = window->priv;
5389
5390   value = value != FALSE;
5391
5392   if (value != priv->has_resize_grip)
5393     {
5394       priv->has_resize_grip = value;
5395       gtk_widget_queue_draw (widget);
5396
5397       if (gtk_widget_get_realized (widget))
5398         {
5399           if (priv->has_resize_grip && priv->grip_window == NULL)
5400             resize_grip_create_window (window);
5401           else if (!priv->has_resize_grip && priv->grip_window != NULL)
5402             resize_grip_destroy_window (window);
5403         }
5404
5405       g_object_notify (G_OBJECT (window), "has-resize-grip");
5406     }
5407 }
5408
5409 static void
5410 update_grip_visibility (GtkWindow *window)
5411 {
5412   GtkWindowPrivate *priv = window->priv;
5413   gboolean val;
5414
5415   val = gtk_window_resize_grip_is_visible (window);
5416
5417   if (priv->grip_window != NULL)
5418     {
5419       if (val)
5420         {
5421           gdk_window_show (priv->grip_window);
5422           set_grip_cursor (window);
5423         }
5424       else
5425         {
5426           gdk_window_hide (priv->grip_window);
5427         }
5428     }
5429
5430   if (priv->resize_grip_visible != val)
5431     {
5432       priv->resize_grip_visible = val;
5433
5434       g_object_notify (G_OBJECT (window), "resize-grip-visible");
5435     }
5436 }
5437
5438 /**
5439  * gtk_window_resize_grip_is_visible:
5440  * @window: a #GtkWindow
5441  *
5442  * Determines whether a resize grip is visible for the specified window.
5443  *
5444  * Returns %TRUE if a resize grip exists and is visible.
5445  *
5446  * Since: 3.0
5447  */
5448 gboolean
5449 gtk_window_resize_grip_is_visible (GtkWindow *window)
5450 {
5451   GtkWidget *widget;
5452   GtkWindowPrivate *priv;
5453   GdkWindowEdge edge;
5454
5455   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5456
5457   priv = window->priv;
5458   widget = GTK_WIDGET (window);
5459
5460   if (priv->type == GTK_WINDOW_POPUP)
5461     return FALSE;
5462
5463   if (!priv->resizable)
5464     return FALSE;
5465
5466   if (gtk_widget_get_realized (widget))
5467     {
5468       GdkWindowState state;
5469
5470       state = gdk_window_get_state (gtk_widget_get_window (widget));
5471
5472       if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
5473         return FALSE;
5474     }
5475
5476   if (!get_drag_edge (widget, &edge))
5477     return FALSE;
5478
5479   return window->priv->has_resize_grip;
5480 }
5481
5482 /**
5483  * gtk_window_get_has_resize_grip:
5484  * @window: a #GtkWindow
5485  *
5486  * Determines whether the window may have a resize grip.
5487  *
5488  * Returns: %TRUE if the window has a resize grip.
5489  *
5490  * Since: 3.0
5491  */
5492 gboolean
5493 gtk_window_get_has_resize_grip (GtkWindow *window)
5494 {
5495   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5496
5497   return window->priv->has_resize_grip;
5498 }
5499
5500 /**
5501  * gtk_window_get_resize_grip_area:
5502  * @window: a #GtkWindow
5503  * @rect: a pointer to a #GdkRectangle which we should store the
5504  *     resize grip area.
5505  *
5506  * If a window has a resize grip, this will retrieve the grip
5507  * position, width and height into the specified #GdkRectangle.
5508  *
5509  * Returns: %TRUE if the resize grip's area was retrieved.
5510  *
5511  * Since: 3.0
5512  */
5513 gboolean
5514 gtk_window_get_resize_grip_area (GtkWindow *window,
5515                                  GdkRectangle *rect)
5516 {
5517   GtkWidget *widget = GTK_WIDGET (window);
5518   GtkAllocation allocation;
5519   gint grip_width;
5520   gint grip_height;
5521
5522   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5523
5524   if (!window->priv->has_resize_grip)
5525     return FALSE;
5526
5527   gtk_widget_get_allocation (widget, &allocation);
5528
5529   gtk_widget_style_get (widget,
5530                         "resize-grip-width", &grip_width,
5531                         "resize-grip-height", &grip_height,
5532                         NULL);
5533
5534   if (grip_width > allocation.width)
5535     grip_width = allocation.width;
5536
5537   if (grip_height > allocation.height)
5538     grip_height = allocation.height;
5539
5540   rect->width = grip_width;
5541   rect->height = grip_height;
5542   rect->y = allocation.y + allocation.height - grip_height;
5543
5544   if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
5545     rect->x = allocation.x + allocation.width - grip_width;
5546   else
5547     rect->x = allocation.x;
5548
5549   return TRUE;
5550 }
5551
5552 /* the accel_key and accel_mods fields of the key have to be setup
5553  * upon calling this function. it'll then return whether that key
5554  * is at all used as accelerator, and if so will OR in the
5555  * accel_flags member of the key.
5556  */
5557 gboolean
5558 _gtk_window_query_nonaccels (GtkWindow      *window,
5559                              guint           accel_key,
5560                              GdkModifierType accel_mods)
5561 {
5562   GtkWindowPrivate *priv;
5563
5564   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5565
5566   priv = window->priv;
5567
5568   /* movement keys are considered locked accels */
5569   if (!accel_mods)
5570     {
5571       static const guint bindings[] = {
5572         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,
5573         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,
5574       };
5575       guint i;
5576       
5577       for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5578         if (bindings[i] == accel_key)
5579           return TRUE;
5580     }
5581
5582   /* mnemonics are considered locked accels */
5583   if (accel_mods == priv->mnemonic_modifier)
5584     {
5585       GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
5586       if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
5587         return TRUE;
5588     }
5589
5590   return FALSE;
5591 }
5592
5593 /**
5594  * gtk_window_propagate_key_event:
5595  * @window:  a #GtkWindow
5596  * @event:   a #GdkEventKey
5597  *
5598  * Propagate a key press or release event to the focus widget and
5599  * up the focus container chain until a widget handles @event.
5600  * This is normally called by the default ::key_press_event and
5601  * ::key_release_event handlers for toplevel windows,
5602  * however in some cases it may be useful to call this directly when
5603  * overriding the standard key handling for a toplevel window.
5604  *
5605  * Return value: %TRUE if a widget in the focus chain handled the event.
5606  *
5607  * Since: 2.4
5608  */
5609 gboolean
5610 gtk_window_propagate_key_event (GtkWindow        *window,
5611                                 GdkEventKey      *event)
5612 {
5613   GtkWindowPrivate *priv;
5614   gboolean handled = FALSE;
5615   GtkWidget *widget, *focus;
5616
5617   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5618
5619   priv = window->priv;
5620   widget = GTK_WIDGET (window);
5621
5622   focus = priv->focus_widget;
5623   if (focus)
5624     g_object_ref (focus);
5625   
5626   while (!handled &&
5627          focus && focus != widget &&
5628          gtk_widget_get_toplevel (focus) == widget)
5629     {
5630       GtkWidget *parent;
5631       
5632       if (gtk_widget_is_sensitive (focus))
5633         handled = gtk_widget_event (focus, (GdkEvent*) event);
5634
5635       parent = gtk_widget_get_parent (focus);
5636       if (parent)
5637         g_object_ref (parent);
5638       
5639       g_object_unref (focus);
5640       
5641       focus = parent;
5642     }
5643   
5644   if (focus)
5645     g_object_unref (focus);
5646
5647   return handled;
5648 }
5649
5650 static gint
5651 gtk_window_key_press_event (GtkWidget   *widget,
5652                             GdkEventKey *event)
5653 {
5654   GtkWindow *window = GTK_WINDOW (widget);
5655   gboolean handled = FALSE;
5656
5657   /* handle mnemonics and accelerators */
5658   if (!handled)
5659     handled = gtk_window_activate_key (window, event);
5660
5661   /* handle focus widget key events */
5662   if (!handled)
5663     handled = gtk_window_propagate_key_event (window, event);
5664
5665   /* Chain up, invokes binding set */
5666   if (!handled)
5667     handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
5668
5669   return handled;
5670 }
5671
5672 static gint
5673 gtk_window_key_release_event (GtkWidget   *widget,
5674                               GdkEventKey *event)
5675 {
5676   GtkWindow *window = GTK_WINDOW (widget);
5677   gboolean handled = FALSE;
5678
5679   /* handle focus widget key events */
5680   if (!handled)
5681     handled = gtk_window_propagate_key_event (window, event);
5682
5683   /* Chain up, invokes binding set */
5684   if (!handled)
5685     handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
5686
5687   return handled;
5688 }
5689
5690 static gint
5691 gtk_window_button_press_event (GtkWidget *widget,
5692                                GdkEventButton *event)
5693 {
5694   GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
5695   GdkWindowEdge edge;
5696
5697   if (event->window == priv->grip_window)
5698     {
5699       if (get_drag_edge (widget, &edge))
5700         gtk_window_begin_resize_drag (GTK_WINDOW (widget),
5701                                       edge,
5702                                       event->button,
5703                                       event->x_root,
5704                                       event->y_root,
5705                                       event->time);
5706
5707       return TRUE;
5708     }
5709
5710   return FALSE;
5711 }
5712
5713 static void
5714 gtk_window_real_activate_default (GtkWindow *window)
5715 {
5716   gtk_window_activate_default (window);
5717 }
5718
5719 static void
5720 gtk_window_real_activate_focus (GtkWindow *window)
5721 {
5722   gtk_window_activate_focus (window);
5723 }
5724
5725 static gint
5726 gtk_window_enter_notify_event (GtkWidget        *widget,
5727                                GdkEventCrossing *event)
5728 {
5729   return FALSE;
5730 }
5731
5732 static gint
5733 gtk_window_leave_notify_event (GtkWidget        *widget,
5734                                GdkEventCrossing *event)
5735 {
5736   return FALSE;
5737 }
5738
5739 static void
5740 do_focus_change (GtkWidget *widget,
5741                  gboolean   in)
5742 {
5743   GdkWindow *window;
5744   GdkDeviceManager *device_manager;
5745   GList *devices, *d;
5746
5747   g_object_ref (widget);
5748
5749   device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
5750   devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
5751   devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
5752   devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
5753
5754   for (d = devices; d; d = d->next)
5755     {
5756       GdkDevice *dev = d->data;
5757       GdkEvent *fevent;
5758
5759       if (gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD)
5760         continue;
5761
5762       /* Skip non-master keyboards that haven't
5763        * selected for events from this window
5764        */
5765       window = gtk_widget_get_window (widget);
5766       if (gdk_device_get_device_type (dev) != GDK_DEVICE_TYPE_MASTER &&
5767           window && !gdk_window_get_device_events (window, dev))
5768         continue;
5769
5770       fevent = gdk_event_new (GDK_FOCUS_CHANGE);
5771
5772       fevent->focus_change.type = GDK_FOCUS_CHANGE;
5773       fevent->focus_change.window = window;
5774       if (window)
5775         g_object_ref (window);
5776       fevent->focus_change.in = in;
5777       gdk_event_set_device (fevent, dev);
5778
5779       gtk_widget_send_focus_change (widget, fevent);
5780
5781       gdk_event_free (fevent);
5782     }
5783
5784   g_list_free (devices);
5785   g_object_unref (widget);
5786 }
5787
5788 static gint
5789 gtk_window_focus_in_event (GtkWidget     *widget,
5790                            GdkEventFocus *event)
5791 {
5792   GtkWindow *window = GTK_WINDOW (widget);
5793
5794   /* It appears spurious focus in events can occur when
5795    *  the window is hidden. So we'll just check to see if
5796    *  the window is visible before actually handling the
5797    *  event
5798    */
5799   if (gtk_widget_get_visible (widget))
5800     {
5801       _gtk_window_set_has_toplevel_focus (window, TRUE);
5802       _gtk_window_set_is_active (window, TRUE);
5803     }
5804       
5805   return FALSE;
5806 }
5807
5808 static gint
5809 gtk_window_focus_out_event (GtkWidget     *widget,
5810                             GdkEventFocus *event)
5811 {
5812   GtkWindow *window = GTK_WINDOW (widget);
5813   gboolean auto_mnemonics;
5814
5815   _gtk_window_set_has_toplevel_focus (window, FALSE);
5816   _gtk_window_set_is_active (window, FALSE);
5817
5818   /* set the mnemonic-visible property to false */
5819   g_object_get (gtk_widget_get_settings (widget),
5820                 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
5821   if (auto_mnemonics)
5822     gtk_window_set_mnemonics_visible (window, FALSE);
5823
5824   return FALSE;
5825 }
5826
5827 static GdkAtom atom_rcfiles = GDK_NONE;
5828 static GdkAtom atom_iconthemes = GDK_NONE;
5829
5830 static void
5831 send_client_message_to_embedded_windows (GtkWidget *widget,
5832                                          GdkAtom    message_type)
5833 {
5834   GList *embedded_windows;
5835
5836   embedded_windows = g_object_get_qdata (G_OBJECT (widget), quark_gtk_embedded);
5837   if (embedded_windows)
5838     {
5839       GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
5840       int i;
5841       
5842       for (i = 0; i < 5; i++)
5843         send_event->client.data.l[i] = 0;
5844       send_event->client.data_format = 32;
5845       send_event->client.message_type = message_type;
5846       
5847       while (embedded_windows)
5848         {
5849           GdkNativeWindow xid = GDK_GPOINTER_TO_NATIVE_WINDOW(embedded_windows->data);
5850           gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
5851           embedded_windows = embedded_windows->next;
5852         }
5853
5854       gdk_event_free (send_event);
5855     }
5856 }
5857
5858 static gint
5859 gtk_window_client_event (GtkWidget      *widget,
5860                          GdkEventClient *event)
5861 {
5862   if (!atom_rcfiles)
5863     {
5864       atom_rcfiles = gdk_atom_intern_static_string ("_GTK_READ_RCFILES");
5865       atom_iconthemes = gdk_atom_intern_static_string ("_GTK_LOAD_ICONTHEMES");
5866     }
5867
5868   if (event->message_type == atom_rcfiles) 
5869     {
5870       send_client_message_to_embedded_windows (widget, atom_rcfiles);
5871       gtk_style_context_reset_widgets (gtk_widget_get_screen (widget));
5872     }
5873
5874   if (event->message_type == atom_iconthemes) 
5875     {
5876       send_client_message_to_embedded_windows (widget, atom_iconthemes);
5877       _gtk_icon_theme_check_reload (gtk_widget_get_display (widget));    
5878     }
5879
5880   return FALSE;
5881 }
5882
5883 static void
5884 gtk_window_check_resize (GtkContainer *container)
5885 {
5886   if (gtk_widget_get_visible (GTK_WIDGET (container)))
5887     gtk_window_move_resize (GTK_WINDOW (container));
5888 }
5889
5890 static gboolean
5891 gtk_window_focus (GtkWidget        *widget,
5892                   GtkDirectionType  direction)
5893 {
5894   GtkWindowPrivate *priv;
5895   GtkBin *bin;
5896   GtkWindow *window;
5897   GtkContainer *container;
5898   GtkWidget *child;
5899   GtkWidget *old_focus_child;
5900   GtkWidget *parent;
5901
5902   container = GTK_CONTAINER (widget);
5903   window = GTK_WINDOW (widget);
5904   priv = window->priv;
5905   bin = GTK_BIN (widget);
5906
5907   old_focus_child = gtk_container_get_focus_child (container);
5908   
5909   /* We need a special implementation here to deal properly with wrapping
5910    * around in the tab chain without the danger of going into an
5911    * infinite loop.
5912    */
5913   if (old_focus_child)
5914     {
5915       if (gtk_widget_child_focus (old_focus_child, direction))
5916         return TRUE;
5917     }
5918
5919   if (priv->focus_widget)
5920     {
5921       if (direction == GTK_DIR_LEFT ||
5922           direction == GTK_DIR_RIGHT ||
5923           direction == GTK_DIR_UP ||
5924           direction == GTK_DIR_DOWN)
5925         {
5926           return FALSE;
5927         }
5928       
5929       /* Wrapped off the end, clear the focus setting for the toplpevel */
5930       parent = gtk_widget_get_parent (priv->focus_widget);
5931       while (parent)
5932         {
5933           gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
5934           parent = gtk_widget_get_parent (parent);
5935         }
5936       
5937       gtk_window_set_focus (GTK_WINDOW (container), NULL);
5938     }
5939
5940   /* Now try to focus the first widget in the window */
5941   child = gtk_bin_get_child (bin);
5942   if (child)
5943     {
5944       if (gtk_widget_child_focus (child, direction))
5945         return TRUE;
5946     }
5947
5948   return FALSE;
5949 }
5950
5951 static void
5952 gtk_window_move_focus (GtkWidget       *widget,
5953                        GtkDirectionType dir)
5954 {
5955   gtk_widget_child_focus (widget, dir);
5956
5957   if (! gtk_container_get_focus_child (GTK_CONTAINER (widget)))
5958     gtk_window_set_focus (GTK_WINDOW (widget), NULL);
5959 }
5960
5961 static void
5962 gtk_window_real_set_focus (GtkWindow *window,
5963                            GtkWidget *focus)
5964 {
5965   GtkWindowPrivate *priv = window->priv;
5966   GtkWidget *old_focus = priv->focus_widget;
5967   gboolean had_default = FALSE;
5968   gboolean focus_had_default = FALSE;
5969   gboolean old_focus_had_default = FALSE;
5970
5971   if (old_focus)
5972     {
5973       g_object_ref (old_focus);
5974       g_object_freeze_notify (G_OBJECT (old_focus));
5975       old_focus_had_default = gtk_widget_has_default (old_focus);
5976     }
5977   if (focus)
5978     {
5979       g_object_ref (focus);
5980       g_object_freeze_notify (G_OBJECT (focus));
5981       focus_had_default = gtk_widget_has_default (focus);
5982     }
5983
5984   if (priv->default_widget)
5985     had_default = gtk_widget_has_default (priv->default_widget);
5986
5987   if (priv->focus_widget)
5988     {
5989       if (gtk_widget_get_receives_default (priv->focus_widget) &&
5990           (priv->focus_widget != priv->default_widget))
5991         {
5992           _gtk_widget_set_has_default (priv->focus_widget, FALSE);
5993           gtk_widget_queue_draw (priv->focus_widget);
5994
5995           if (priv->default_widget)
5996             _gtk_widget_set_has_default (priv->default_widget, TRUE);
5997         }
5998
5999       priv->focus_widget = NULL;
6000
6001       if (priv->has_focus)
6002         do_focus_change (old_focus, FALSE);
6003
6004       g_object_notify (G_OBJECT (old_focus), "is-focus");
6005     }
6006
6007   /* The above notifications may have set a new focus widget,
6008    * if so, we don't want to override it.
6009    */
6010   if (focus && !priv->focus_widget)
6011     {
6012       priv->focus_widget = focus;
6013
6014       if (gtk_widget_get_receives_default (priv->focus_widget) &&
6015           (priv->focus_widget != priv->default_widget))
6016         {
6017           if (gtk_widget_get_can_default (priv->focus_widget))
6018             _gtk_widget_set_has_default (priv->focus_widget, TRUE);
6019
6020           if (priv->default_widget)
6021             _gtk_widget_set_has_default (priv->default_widget, FALSE);
6022         }
6023
6024       if (priv->has_focus)
6025         do_focus_change (priv->focus_widget, TRUE);
6026
6027       g_object_notify (G_OBJECT (priv->focus_widget), "is-focus");
6028     }
6029
6030   /* If the default widget changed, a redraw will have been queued
6031    * on the old and new default widgets by gtk_window_set_default(), so
6032    * we only have to worry about the case where it didn't change.
6033    * We'll sometimes queue a draw twice on the new widget but that
6034    * is harmless.
6035    */
6036   if (priv->default_widget &&
6037       (had_default != gtk_widget_has_default (priv->default_widget)))
6038     gtk_widget_queue_draw (priv->default_widget);
6039   
6040   if (old_focus)
6041     {
6042       if (old_focus_had_default != gtk_widget_has_default (old_focus))
6043         gtk_widget_queue_draw (old_focus);
6044         
6045       g_object_thaw_notify (G_OBJECT (old_focus));
6046       g_object_unref (old_focus);
6047     }
6048   if (focus)
6049     {
6050       if (focus_had_default != gtk_widget_has_default (focus))
6051         gtk_widget_queue_draw (focus);
6052
6053       g_object_thaw_notify (G_OBJECT (focus));
6054       g_object_unref (focus);
6055     }
6056 }
6057
6058
6059 static void 
6060 gtk_window_get_preferred_width (GtkWidget *widget,
6061                                 gint      *minimum_size,
6062                                 gint      *natural_size)
6063 {
6064   GtkWindow *window;
6065   GtkWidget *child;
6066   guint border_width;
6067
6068   window = GTK_WINDOW (widget);
6069   child  = gtk_bin_get_child (GTK_BIN (window));
6070
6071   border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6072   *minimum_size = border_width * 2;
6073   *natural_size = border_width * 2;
6074
6075   if (child && gtk_widget_get_visible (child))
6076     {
6077       gint child_min, child_nat;
6078       gtk_widget_get_preferred_width (child, &child_min, &child_nat);
6079
6080       *minimum_size += child_min;
6081       *natural_size += child_nat;
6082     }
6083 }
6084
6085 static void 
6086 gtk_window_get_preferred_height (GtkWidget *widget,
6087                                  gint      *minimum_size,
6088                                  gint      *natural_size)
6089 {
6090   GtkWindow *window;
6091   GtkWidget *child;
6092   guint border_width;
6093
6094   window = GTK_WINDOW (widget);
6095   child  = gtk_bin_get_child (GTK_BIN (window));
6096
6097   border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
6098   *minimum_size = border_width * 2;
6099   *natural_size = border_width * 2;
6100
6101   if (child && gtk_widget_get_visible (child))
6102     {
6103       gint child_min, child_nat;
6104       gtk_widget_get_preferred_height (child, &child_min, &child_nat);
6105
6106       *minimum_size += child_min;
6107       *natural_size += child_nat;
6108     }
6109 }
6110
6111
6112 /**
6113  * _gtk_window_unset_focus_and_default:
6114  * @window: a #GtkWindow
6115  * @widget: a widget inside of @window
6116  * 
6117  * Checks whether the focus and default widgets of @window are
6118  * @widget or a descendent of @widget, and if so, unset them.
6119  **/
6120 void
6121 _gtk_window_unset_focus_and_default (GtkWindow *window,
6122                                      GtkWidget *widget)
6123
6124 {
6125   GtkWindowPrivate *priv = window->priv;
6126   GtkWidget *child;
6127   GtkWidget *parent;
6128
6129   g_object_ref (window);
6130   g_object_ref (widget);
6131
6132   parent = gtk_widget_get_parent (widget);
6133   if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget)
6134     {
6135       child = priv->focus_widget;
6136       
6137       while (child && child != widget)
6138         child = gtk_widget_get_parent (child);
6139
6140       if (child == widget)
6141         gtk_window_set_focus (GTK_WINDOW (window), NULL);
6142     }
6143       
6144   child = priv->default_widget;
6145       
6146   while (child && child != widget)
6147     child = gtk_widget_get_parent (child);
6148
6149   if (child == widget)
6150     gtk_window_set_default (window, NULL);
6151   
6152   g_object_unref (widget);
6153   g_object_unref (window);
6154 }
6155
6156 /*********************************
6157  * Functions related to resizing *
6158  *********************************/
6159
6160 static void
6161 geometry_size_to_pixels (GdkGeometry *geometry,
6162                          guint        flags,
6163                          guint       *width,
6164                          guint       *height)
6165 {
6166   gint base_width = 0;
6167   gint base_height = 0;
6168   gint min_width = 0;
6169   gint min_height = 0;
6170   gint width_inc = 1;
6171   gint height_inc = 1;
6172
6173   if (flags & GDK_HINT_BASE_SIZE)
6174     {
6175       base_width = geometry->base_width;
6176       base_height = geometry->base_height;
6177     }
6178   if (flags & GDK_HINT_MIN_SIZE)
6179     {
6180       min_width = geometry->min_width;
6181       min_height = geometry->min_height;
6182     }
6183   if (flags & GDK_HINT_RESIZE_INC)
6184     {
6185       width_inc = geometry->width_inc;
6186       height_inc = geometry->height_inc;
6187     }
6188
6189   if (width)
6190     *width = MAX (*width * width_inc + base_width, min_width);
6191   if (height)
6192     *height = MAX (*height * height_inc + base_height, min_height);
6193 }
6194
6195 /* This function doesn't constrain to geometry hints */
6196 static void 
6197 gtk_window_compute_configure_request_size (GtkWindow   *window,
6198                                            GdkGeometry *geometry,
6199                                            guint        flags,
6200                                            guint       *width,
6201                                            guint       *height)
6202 {
6203   GtkWindowPrivate *priv = window->priv;
6204   GtkRequisition requisition;
6205   GtkWindowGeometryInfo *info;
6206   GtkWidget *widget;
6207
6208   /* Preconditions:
6209    *  - we've done a size request
6210    */
6211   
6212   widget = GTK_WIDGET (window);
6213
6214   info = gtk_window_get_geometry_info (window, FALSE);
6215
6216   if (priv->need_default_size)
6217     {
6218       gtk_widget_get_preferred_size (widget, &requisition, NULL);
6219
6220       /* Default to requisition */
6221       *width = requisition.width;
6222       *height = requisition.height;
6223
6224       /* If window is empty so requests 0, default to random nonzero size */
6225        if (*width == 0 && *height == 0)
6226          {
6227            *width = 200;
6228            *height = 200;
6229          }
6230
6231        /* Override requisition with default size */
6232
6233        if (info)
6234          {
6235            if (info->default_width > 0)
6236              *width = info->default_width;
6237            if (info->default_height > 0)
6238              *height = info->default_height;
6239
6240            if (info->default_is_geometry)
6241              geometry_size_to_pixels (geometry, flags,
6242                                       info->default_width > 0 ? width : NULL,
6243                                       info->default_height > 0 ? height : NULL);
6244          }
6245     }
6246   else
6247     {
6248       GtkAllocation allocation;
6249
6250       gtk_widget_get_allocation (widget, &allocation);
6251
6252       /* Default to keeping current size */
6253       *width = allocation.width;
6254       *height = allocation.height;
6255     }
6256
6257   /* Override any size with gtk_window_resize() values */
6258   if (info)
6259     {
6260       if (info->resize_width > 0)
6261         *width = info->resize_width;
6262       if (info->resize_height > 0)
6263         *height = info->resize_height;
6264
6265       if (info->resize_is_geometry)
6266         geometry_size_to_pixels (geometry, flags,
6267                                  info->resize_width > 0 ? width : NULL,
6268                                  info->resize_height > 0 ? height : NULL);
6269     }
6270
6271   /* Don't ever request zero width or height, its not supported by
6272      gdk. The size allocation code will round it to 1 anyway but if
6273      we do it then the value returned from this function will is
6274      not comparable to the size allocation read from the GtkWindow. */
6275   *width = MAX (*width, 1);
6276   *height = MAX (*height, 1);
6277 }
6278
6279 static GtkWindowPosition
6280 get_effective_position (GtkWindow *window)
6281 {
6282   GtkWindowPrivate *priv = window->priv;
6283   GtkWindowPosition pos = priv->position;
6284
6285   if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
6286       (priv->transient_parent == NULL ||
6287        !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent))))
6288     pos = GTK_WIN_POS_NONE;
6289
6290   return pos;
6291 }
6292
6293 static int
6294 get_center_monitor_of_window (GtkWindow *window)
6295 {
6296   /* We could try to sort out the relative positions of the monitors and
6297    * stuff, or we could just be losers and assume you have a row
6298    * or column of monitors.
6299    */
6300   return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
6301 }
6302
6303 static int
6304 get_monitor_containing_pointer (GtkWindow *window)
6305 {
6306   gint px, py;
6307   gint monitor_num;
6308   GdkScreen *window_screen;
6309   GdkScreen *pointer_screen;
6310   GdkDisplay *display;
6311   GdkDeviceManager *device_manager;
6312   GdkDevice *pointer;
6313
6314   window_screen = gtk_window_check_screen (window);
6315   display = gdk_screen_get_display (window_screen);
6316   device_manager = gdk_display_get_device_manager (display);
6317   pointer = gdk_device_manager_get_client_pointer (device_manager);
6318
6319   gdk_display_get_device_state (display, pointer,
6320                                 &pointer_screen,
6321                                 &px, &py, NULL);
6322
6323   if (pointer_screen == window_screen)
6324     monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
6325   else
6326     monitor_num = -1;
6327
6328   return monitor_num;
6329 }
6330
6331 static void
6332 center_window_on_monitor (GtkWindow *window,
6333                           gint       w,
6334                           gint       h,
6335                           gint      *x,
6336                           gint      *y)
6337 {
6338   GdkRectangle monitor;
6339   int monitor_num;
6340
6341   monitor_num = get_monitor_containing_pointer (window);
6342   
6343   if (monitor_num == -1)
6344     monitor_num = get_center_monitor_of_window (window);
6345
6346   gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
6347                                    monitor_num, &monitor);
6348   
6349   *x = (monitor.width - w) / 2 + monitor.x;
6350   *y = (monitor.height - h) / 2 + monitor.y;
6351
6352   /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
6353    * and WM decorations.
6354    */
6355   if (*x < monitor.x)
6356     *x = monitor.x;
6357   if (*y < monitor.y)
6358     *y = monitor.y;
6359 }
6360
6361 static void
6362 clamp (gint *base,
6363        gint  extent,
6364        gint  clamp_base,
6365        gint  clamp_extent)
6366 {
6367   if (extent > clamp_extent)
6368     /* Center */
6369     *base = clamp_base + clamp_extent/2 - extent/2;
6370   else if (*base < clamp_base)
6371     *base = clamp_base;
6372   else if (*base + extent > clamp_base + clamp_extent)
6373     *base = clamp_base + clamp_extent - extent;
6374 }
6375
6376 static void
6377 clamp_window_to_rectangle (gint               *x,
6378                            gint               *y,
6379                            gint                w,
6380                            gint                h,
6381                            const GdkRectangle *rect)
6382 {
6383 #ifdef DEBUGGING_OUTPUT
6384   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);
6385 #endif
6386
6387   /* If it is too large, center it. If it fits on the monitor but is
6388    * partially outside, move it to the closest edge. Do this
6389    * separately in x and y directions.
6390    */
6391   clamp (x, w, rect->x, rect->width);
6392   clamp (y, h, rect->y, rect->height);
6393 #ifdef DEBUGGING_OUTPUT
6394   g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
6395 #endif
6396 }
6397
6398
6399 static void
6400 gtk_window_compute_configure_request (GtkWindow    *window,
6401                                       GdkRectangle *request,
6402                                       GdkGeometry  *geometry,
6403                                       guint        *flags)
6404 {
6405   GtkWindowPrivate *priv = window->priv;
6406   GdkGeometry new_geometry;
6407   guint new_flags;
6408   int w, h;
6409   GtkWidget *widget;
6410   GtkWindowPosition pos;
6411   GtkWidget *parent_widget;
6412   GtkWindowGeometryInfo *info;
6413   GdkScreen *screen;
6414   int x, y;
6415   
6416   widget = GTK_WIDGET (window);
6417
6418   screen = gtk_window_check_screen (window);
6419
6420   gtk_window_compute_hints (window, &new_geometry, &new_flags);
6421   gtk_window_compute_configure_request_size (window,
6422                                              &new_geometry, new_flags,
6423                                              (guint *)&w, (guint *)&h);
6424
6425   gtk_window_constrain_size (window,
6426                              &new_geometry, new_flags,
6427                              w, h,
6428                              &w, &h);
6429
6430   parent_widget = (GtkWidget*) priv->transient_parent;
6431   
6432   pos = get_effective_position (window);
6433   info = gtk_window_get_geometry_info (window, FALSE);
6434   
6435   /* by default, don't change position requested */
6436   if (info)
6437     {
6438       x = info->last.configure_request.x;
6439       y = info->last.configure_request.y;
6440     }
6441   else
6442     {
6443       x = 0;
6444       y = 0;
6445     }
6446
6447
6448   if (priv->need_default_position)
6449     {
6450
6451       /* FIXME this all interrelates with window gravity.
6452        * For most of them I think we want to set GRAVITY_CENTER.
6453        *
6454        * Not sure how to go about that.
6455        */
6456       
6457       switch (pos)
6458         {
6459           /* here we are only handling CENTER_ALWAYS
6460            * as it relates to default positioning,
6461            * where it's equivalent to simply CENTER
6462            */
6463         case GTK_WIN_POS_CENTER_ALWAYS:
6464         case GTK_WIN_POS_CENTER:
6465           center_window_on_monitor (window, w, h, &x, &y);
6466           break;
6467       
6468         case GTK_WIN_POS_CENTER_ON_PARENT:
6469           {
6470             GtkAllocation allocation;
6471             GdkWindow *gdk_window;
6472             gint monitor_num;
6473             GdkRectangle monitor;
6474             gint ox, oy;
6475             
6476             g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
6477
6478             gdk_window = gtk_widget_get_window (parent_widget);
6479
6480             if (gdk_window != NULL)
6481               monitor_num = gdk_screen_get_monitor_at_window (screen,
6482                                                               gdk_window);
6483             else
6484               monitor_num = -1;
6485
6486             gdk_window_get_origin (gdk_window,
6487                                    &ox, &oy);
6488
6489             gtk_widget_get_allocation (parent_widget, &allocation);
6490             x = ox + (allocation.width - w) / 2;
6491             y = oy + (allocation.height - h) / 2;
6492
6493             /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6494              * WM decorations. If parent wasn't on a monitor, just
6495              * give up.
6496              */
6497             if (monitor_num >= 0)
6498               {
6499                 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6500                 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6501               }
6502           }
6503           break;
6504
6505         case GTK_WIN_POS_MOUSE:
6506           {
6507             gint screen_width = gdk_screen_get_width (screen);
6508             gint screen_height = gdk_screen_get_height (screen);
6509             gint monitor_num;
6510             GdkRectangle monitor;
6511             GdkDisplay *display;
6512             GdkDeviceManager *device_manager;
6513             GdkDevice *pointer;
6514             GdkScreen *pointer_screen;
6515             gint px, py;
6516
6517             display = gdk_screen_get_display (screen);
6518             device_manager = gdk_display_get_device_manager (display);
6519             pointer = gdk_device_manager_get_client_pointer (device_manager);
6520
6521             gdk_display_get_device_state (display, pointer,
6522                                           &pointer_screen,
6523                                           &px, &py, NULL);
6524
6525             if (pointer_screen == screen)
6526               monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
6527             else
6528               monitor_num = -1;
6529             
6530             x = px - w / 2;
6531             y = py - h / 2;
6532             x = CLAMP (x, 0, screen_width - w);
6533             y = CLAMP (y, 0, screen_height - h);
6534
6535             /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
6536              * WM decorations. Don't try to figure out what's going
6537              * on if the mouse wasn't inside a monitor.
6538              */
6539             if (monitor_num >= 0)
6540               {
6541                 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
6542                 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
6543               }
6544           }
6545           break;
6546
6547         default:
6548           break;
6549         }
6550     } /* if (priv->need_default_position) */
6551
6552   if (priv->need_default_position && info &&
6553       info->initial_pos_set)
6554     {
6555       x = info->initial_x;
6556       y = info->initial_y;
6557       gtk_window_constrain_position (window, w, h, &x, &y);
6558     }
6559   
6560   request->x = x;
6561   request->y = y;
6562   request->width = w;
6563   request->height = h;
6564
6565   if (geometry)
6566     *geometry = new_geometry;
6567   if (flags)
6568     *flags = new_flags;
6569 }
6570
6571 static void
6572 gtk_window_constrain_position (GtkWindow    *window,
6573                                gint          new_width,
6574                                gint          new_height,
6575                                gint         *x,
6576                                gint         *y)
6577 {
6578   GtkWindowPrivate *priv = window->priv;
6579
6580   /* See long comments in gtk_window_move_resize()
6581    * on when it's safe to call this function.
6582    */
6583   if (priv->position == GTK_WIN_POS_CENTER_ALWAYS)
6584     {
6585       gint center_x, center_y;
6586
6587       center_window_on_monitor (window, new_width, new_height, &center_x, &center_y);
6588       
6589       *x = center_x;
6590       *y = center_y;
6591     }
6592 }
6593
6594 static void
6595 gtk_window_move_resize (GtkWindow *window)
6596 {
6597   /* Overview:
6598    *
6599    * First we determine whether any information has changed that would
6600    * cause us to revise our last configure request.  If we would send
6601    * a different configure request from last time, then
6602    * configure_request_size_changed = TRUE or
6603    * configure_request_pos_changed = TRUE. configure_request_size_changed
6604    * may be true due to new hints, a gtk_window_resize(), or whatever.
6605    * configure_request_pos_changed may be true due to gtk_window_set_position()
6606    * or gtk_window_move().
6607    *
6608    * If the configure request has changed, we send off a new one.  To
6609    * ensure GTK+ invariants are maintained (resize queue does what it
6610    * should), we go ahead and size_allocate the requested size in this
6611    * function.
6612    *
6613    * If the configure request has not changed, we don't ever resend
6614    * it, because it could mean fighting the user or window manager.
6615    *
6616    * 
6617    *   To prepare the configure request, we come up with a base size/pos:
6618    *      - the one from gtk_window_move()/gtk_window_resize()
6619    *      - else default_width, default_height if we haven't ever
6620    *        been mapped
6621    *      - else the size request if we haven't ever been mapped,
6622    *        as a substitute default size
6623    *      - else the current size of the window, as received from
6624    *        configure notifies (i.e. the current allocation)
6625    *
6626    *   If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
6627    *   the position request to be centered.
6628    */
6629   GtkWindowPrivate *priv = window->priv;
6630   GtkAllocation allocation;
6631   GtkWidget *widget;
6632   GtkContainer *container;
6633   GtkWindowGeometryInfo *info;
6634   GdkGeometry new_geometry;
6635   GdkWindow *gdk_window;
6636   guint new_flags;
6637   GdkRectangle new_request;
6638   gboolean configure_request_size_changed;
6639   gboolean configure_request_pos_changed;
6640   gboolean hints_changed; /* do we need to send these again */
6641   GtkWindowLastGeometryInfo saved_last_info;
6642   
6643   widget = GTK_WIDGET (window);
6644   gdk_window = gtk_widget_get_window (widget);
6645   container = GTK_CONTAINER (widget);
6646   info = gtk_window_get_geometry_info (window, TRUE);
6647   
6648   configure_request_size_changed = FALSE;
6649   configure_request_pos_changed = FALSE;
6650   
6651   gtk_window_compute_configure_request (window, &new_request,
6652                                         &new_geometry, &new_flags);  
6653   
6654   /* This check implies the invariant that we never set info->last
6655    * without setting the hints and sending off a configure request.
6656    *
6657    * If we change info->last without sending the request, we may
6658    * miss a request.
6659    */
6660   if (info->last.configure_request.x != new_request.x ||
6661       info->last.configure_request.y != new_request.y)
6662     configure_request_pos_changed = TRUE;
6663
6664   if ((info->last.configure_request.width != new_request.width ||
6665        info->last.configure_request.height != new_request.height))
6666     configure_request_size_changed = TRUE;
6667   
6668   hints_changed = FALSE;
6669   
6670   if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
6671                                  &new_geometry, new_flags))
6672     {
6673       hints_changed = TRUE;
6674     }
6675   
6676   /* Position Constraints
6677    * ====================
6678    * 
6679    * POS_CENTER_ALWAYS is conceptually a constraint rather than
6680    * a default. The other POS_ values are used only when the
6681    * window is shown, not after that.
6682    * 
6683    * However, we can't implement a position constraint as
6684    * "anytime the window size changes, center the window"
6685    * because this may well end up fighting the WM or user.  In
6686    * fact it gets in an infinite loop with at least one WM.
6687    *
6688    * Basically, applications are in no way in a position to
6689    * constrain the position of a window, with one exception:
6690    * override redirect windows. (Really the intended purpose
6691    * of CENTER_ALWAYS anyhow, I would think.)
6692    *
6693    * So the way we implement this "constraint" is to say that when WE
6694    * cause a move or resize, i.e. we make a configure request changing
6695    * window size, we recompute the CENTER_ALWAYS position to reflect
6696    * the new window size, and include it in our request.  Also, if we
6697    * just turned on CENTER_ALWAYS we snap to center with a new
6698    * request.  Otherwise, if we are just NOTIFIED of a move or resize
6699    * done by someone else e.g. the window manager, we do NOT send a
6700    * new configure request.
6701    *
6702    * For override redirect windows, this works fine; all window
6703    * sizes are from our configure requests. For managed windows,
6704    * it is at least semi-sane, though who knows what the
6705    * app author is thinking.
6706    */
6707
6708   /* This condition should be kept in sync with the condition later on
6709    * that determines whether we send a configure request.  i.e. we
6710    * should do this position constraining anytime we were going to
6711    * send a configure request anyhow, plus when constraints have
6712    * changed.
6713    */
6714   if (configure_request_pos_changed ||
6715       configure_request_size_changed ||
6716       hints_changed ||
6717       info->position_constraints_changed)
6718     {
6719       /* We request the constrained position if:
6720        *  - we were changing position, and need to clamp
6721        *    the change to the constraint
6722        *  - we're changing the size anyway
6723        *  - set_position() was called to toggle CENTER_ALWAYS on
6724        */
6725
6726       gtk_window_constrain_position (window,
6727                                      new_request.width,
6728                                      new_request.height,
6729                                      &new_request.x,
6730                                      &new_request.y);
6731       
6732       /* Update whether we need to request a move */
6733       if (info->last.configure_request.x != new_request.x ||
6734           info->last.configure_request.y != new_request.y)
6735         configure_request_pos_changed = TRUE;
6736       else
6737         configure_request_pos_changed = FALSE;
6738     }
6739
6740 #if 0
6741   if (priv->type == GTK_WINDOW_TOPLEVEL)
6742     {
6743       int notify_x, notify_y;
6744
6745       /* this is the position from the last configure notify */
6746       gdk_window_get_position (widget->window, &notify_x, &notify_y);
6747     
6748       g_message ("--- %s ---\n"
6749                  "last  : %d,%d\t%d x %d\n"
6750                  "this  : %d,%d\t%d x %d\n"
6751                  "alloc : %d,%d\t%d x %d\n"
6752                  "req   :      \t%d x %d\n"
6753                  "resize:      \t%d x %d\n" 
6754                  "size_changed: %d pos_changed: %d hints_changed: %d\n"
6755                  "configure_notify_received: %d\n"
6756                  "configure_request_count: %d\n"
6757                  "position_constraints_changed: %d\n",
6758                  priv->title ? priv->title : "(no title)",
6759                  info->last.configure_request.x,
6760                  info->last.configure_request.y,
6761                  info->last.configure_request.width,
6762                  info->last.configure_request.height,
6763                  new_request.x,
6764                  new_request.y,
6765                  new_request.width,
6766                  new_request.height,
6767                  notify_x, notify_y,
6768                  widget->allocation.width,
6769                  widget->allocation.height,
6770                  widget->requisition.width,
6771                  widget->requisition.height,
6772                  info->resize_width,
6773                  info->resize_height,
6774                  configure_request_pos_changed,
6775                  configure_request_size_changed,
6776                  hints_changed,
6777                  priv->configure_notify_received,
6778                  priv->configure_request_count,
6779                  info->position_constraints_changed);
6780     }
6781 #endif
6782   
6783   saved_last_info = info->last;
6784   info->last.geometry = new_geometry;
6785   info->last.flags = new_flags;
6786   info->last.configure_request = new_request;
6787   
6788   /* need to set PPosition so the WM will look at our position,
6789    * but we don't want to count PPosition coming and going as a hints
6790    * change for future iterations. So we saved info->last prior to
6791    * this.
6792    */
6793   
6794   /* Also, if the initial position was explicitly set, then we always
6795    * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
6796    * work.
6797    */
6798
6799   /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
6800    * this is an initial map
6801    */
6802   
6803   if ((configure_request_pos_changed ||
6804        info->initial_pos_set ||
6805        (priv->need_default_position &&
6806         get_effective_position (window) != GTK_WIN_POS_NONE)) &&
6807       (new_flags & GDK_HINT_POS) == 0)
6808     {
6809       new_flags |= GDK_HINT_POS;
6810       hints_changed = TRUE;
6811     }
6812   
6813   /* Set hints if necessary
6814    */
6815   if (hints_changed)
6816     gdk_window_set_geometry_hints (gdk_window,
6817                                    &new_geometry,
6818                                    new_flags);
6819
6820   gtk_widget_get_allocation (widget, &allocation);
6821
6822   /* handle resizing/moving and widget tree allocation
6823    */
6824   if (priv->configure_notify_received)
6825     { 
6826       /* If we have received a configure event since
6827        * the last time in this function, we need to
6828        * accept our new size and size_allocate child widgets.
6829        * (see gtk_window_configure_event() for more details).
6830        *
6831        * 1 or more configure notifies may have been received.
6832        * Also, configure_notify_received will only be TRUE
6833        * if all expected configure notifies have been received
6834        * (one per configure request), as an optimization.
6835        *
6836        */
6837       priv->configure_notify_received = FALSE;
6838
6839       /* gtk_window_configure_event() filled in widget->allocation */
6840       gtk_widget_size_allocate (widget, &allocation);
6841
6842       set_grip_position (window);
6843       update_grip_visibility (window);
6844
6845       gdk_window_process_updates (gdk_window, TRUE);
6846
6847       gdk_window_configure_finished (gdk_window);
6848
6849       /* If the configure request changed, it means that
6850        * we either:
6851        *   1) coincidentally changed hints or widget properties
6852        *      impacting the configure request before getting
6853        *      a configure notify, or
6854        *   2) some broken widget is changing its size request
6855        *      during size allocation, resulting in
6856        *      a false appearance of changed configure request.
6857        *
6858        * For 1), we could just go ahead and ask for the
6859        * new size right now, but doing that for 2)
6860        * might well be fighting the user (and can even
6861        * trigger a loop). Since we really don't want to
6862        * do that, we requeue a resize in hopes that
6863        * by the time it gets handled, the child has seen
6864        * the light and is willing to go along with the
6865        * new size. (this happens for the zvt widget, since
6866        * the size_allocate() above will have stored the
6867        * requisition corresponding to the new size in the
6868        * zvt widget)
6869        *
6870        * This doesn't buy us anything for 1), but it shouldn't
6871        * hurt us too badly, since it is what would have
6872        * happened if we had gotten the configure event before
6873        * the new size had been set.
6874        */
6875
6876       if (configure_request_size_changed ||
6877           configure_request_pos_changed)
6878         {
6879           /* Don't change the recorded last info after all, because we
6880            * haven't actually updated to the new info yet - we decided
6881            * to postpone our configure request until later.
6882            */
6883           info->last = saved_last_info;
6884           
6885           gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
6886         }
6887
6888       return;                   /* Bail out, we didn't really process the move/resize */
6889     }
6890   else if ((configure_request_size_changed || hints_changed) &&
6891            (allocation.width != new_request.width || allocation.height != new_request.height))
6892
6893     {
6894       /* We are in one of the following situations:
6895        * A. configure_request_size_changed
6896        *    our requisition has changed and we need a different window size,
6897        *    so we request it from the window manager.
6898        * B. !configure_request_size_changed && hints_changed
6899        *    the window manager rejects our size, but we have just changed the
6900        *    window manager hints, so there's a chance our request will
6901        *    be honoured this time, so we try again.
6902        *
6903        * However, if the new requisition is the same as the current allocation,
6904        * we don't request it again, since we won't get a ConfigureNotify back from
6905        * the window manager unless it decides to change our requisition. If
6906        * we don't get the ConfigureNotify back, the resize queue will never be run.
6907        */
6908
6909       /* Now send the configure request */
6910       if (configure_request_pos_changed)
6911         {
6912           gdk_window_move_resize (gdk_window,
6913                                   new_request.x, new_request.y,
6914                                   new_request.width, new_request.height);
6915         }
6916       else  /* only size changed */
6917         {
6918           gdk_window_resize (gdk_window,
6919                              new_request.width, new_request.height);
6920         }
6921
6922       if (priv->type == GTK_WINDOW_POPUP)
6923         {
6924           GtkAllocation allocation;
6925
6926           /* Directly size allocate for override redirect (popup) windows. */
6927           allocation.x = 0;
6928           allocation.y = 0;
6929           allocation.width = new_request.width;
6930           allocation.height = new_request.height;
6931
6932           gtk_widget_size_allocate (widget, &allocation);
6933
6934           gdk_window_process_updates (gdk_window, TRUE);
6935
6936           if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
6937             gtk_widget_queue_draw (widget);
6938         }
6939       else
6940         {
6941           /* Increment the number of have-not-yet-received-notify requests */
6942           priv->configure_request_count += 1;
6943           gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
6944
6945           /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
6946            * configure event in response to our resizing request.
6947            * the configure event will cause a new resize with
6948            * ->configure_notify_received=TRUE.
6949            * until then, we want to
6950            * - discard expose events
6951            * - coalesce resizes for our children
6952            * - defer any window resizes until the configure event arrived
6953            * to achieve this, we queue a resize for the window, but remove its
6954            * resizing handler, so resizing will not be handled from the next
6955            * idle handler but when the configure event arrives.
6956            *
6957            * FIXME: we should also dequeue the pending redraws here, since
6958            * we handle those ourselves upon ->configure_notify_received==TRUE.
6959            */
6960           if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
6961             {
6962               gtk_widget_queue_resize_no_redraw (widget);
6963               _gtk_container_dequeue_resize_handler (container);
6964             }
6965         }
6966     }
6967   else
6968     {
6969       /* Handle any position changes.
6970        */
6971       if (configure_request_pos_changed)
6972         {
6973           gdk_window_move (gdk_window,
6974                            new_request.x, new_request.y);
6975         }
6976
6977       /* And run the resize queue.
6978        */
6979       gtk_container_resize_children (container);
6980     }
6981   
6982   /* We have now processed a move/resize since the last position
6983    * constraint change, setting of the initial position, or resize.
6984    * (Not resetting these flags here can lead to infinite loops for
6985    * GTK_RESIZE_IMMEDIATE containers)
6986    */
6987   info->position_constraints_changed = FALSE;
6988   info->initial_pos_set = FALSE;
6989   info->resize_width = -1;
6990   info->resize_height = -1;
6991 }
6992
6993 /* Compare two sets of Geometry hints for equality.
6994  */
6995 static gboolean
6996 gtk_window_compare_hints (GdkGeometry *geometry_a,
6997                           guint        flags_a,
6998                           GdkGeometry *geometry_b,
6999                           guint        flags_b)
7000 {
7001   if (flags_a != flags_b)
7002     return FALSE;
7003   
7004   if ((flags_a & GDK_HINT_MIN_SIZE) &&
7005       (geometry_a->min_width != geometry_b->min_width ||
7006        geometry_a->min_height != geometry_b->min_height))
7007     return FALSE;
7008
7009   if ((flags_a & GDK_HINT_MAX_SIZE) &&
7010       (geometry_a->max_width != geometry_b->max_width ||
7011        geometry_a->max_height != geometry_b->max_height))
7012     return FALSE;
7013
7014   if ((flags_a & GDK_HINT_BASE_SIZE) &&
7015       (geometry_a->base_width != geometry_b->base_width ||
7016        geometry_a->base_height != geometry_b->base_height))
7017     return FALSE;
7018
7019   if ((flags_a & GDK_HINT_ASPECT) &&
7020       (geometry_a->min_aspect != geometry_b->min_aspect ||
7021        geometry_a->max_aspect != geometry_b->max_aspect))
7022     return FALSE;
7023
7024   if ((flags_a & GDK_HINT_RESIZE_INC) &&
7025       (geometry_a->width_inc != geometry_b->width_inc ||
7026        geometry_a->height_inc != geometry_b->height_inc))
7027     return FALSE;
7028
7029   if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
7030       geometry_a->win_gravity != geometry_b->win_gravity)
7031     return FALSE;
7032
7033   return TRUE;
7034 }
7035
7036 void
7037 _gtk_window_constrain_size (GtkWindow   *window,
7038                             gint         width,
7039                             gint         height,
7040                             gint        *new_width,
7041                             gint        *new_height)
7042 {
7043   GtkWindowPrivate *priv;
7044   GtkWindowGeometryInfo *info;
7045
7046   g_return_if_fail (GTK_IS_WINDOW (window));
7047
7048   priv = window->priv;
7049
7050   info = priv->geometry_info;
7051   if (info)
7052     {
7053       GdkWindowHints flags = info->last.flags;
7054       GdkGeometry *geometry = &info->last.geometry;
7055       
7056       gtk_window_constrain_size (window,
7057                                  geometry,
7058                                  flags,
7059                                  width,
7060                                  height,
7061                                  new_width,
7062                                  new_height);
7063     }
7064 }
7065
7066 static void 
7067 gtk_window_constrain_size (GtkWindow   *window,
7068                            GdkGeometry *geometry,
7069                            guint        flags,
7070                            gint         width,
7071                            gint         height,
7072                            gint        *new_width,
7073                            gint        *new_height)
7074 {
7075   gdk_window_constrain_size (geometry, flags, width, height,
7076                              new_width, new_height);
7077 }
7078
7079 /* Compute the set of geometry hints and flags for a window
7080  * based on the application set geometry, and requisition
7081  * of the window. gtk_widget_get_preferred_size() must have been
7082  * called first.
7083  */
7084 static void
7085 gtk_window_compute_hints (GtkWindow   *window,
7086                           GdkGeometry *new_geometry,
7087                           guint       *new_flags)
7088 {
7089   GtkWindowPrivate *priv = window->priv;
7090   GtkWidget *widget;
7091   gint extra_width = 0;
7092   gint extra_height = 0;
7093   GtkWindowGeometryInfo *geometry_info;
7094   GtkRequisition requisition;
7095
7096   widget = GTK_WIDGET (window);
7097
7098   gtk_widget_get_preferred_size (widget, &requisition, NULL);
7099   geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
7100
7101   if (geometry_info)
7102     {
7103       *new_flags = geometry_info->mask;
7104       *new_geometry = geometry_info->geometry;
7105     }
7106   else
7107     {
7108       *new_flags = 0;
7109     }
7110   
7111   if (geometry_info && geometry_info->widget)
7112     {
7113       /* If the geometry widget is set, then the hints really apply to that
7114        * widget. This is pretty much meaningless unless the window layout
7115        * is such that the rest of the window adds fixed size borders to
7116        * the geometry widget. Our job is to figure the size of the borders;
7117        * We do that by asking how big the toplevel would be if the
7118        * geometry widget was *really big*.
7119        *
7120        *  +----------+
7121        *  |AAAAAAAAA | At small sizes, the minimum sizes of widgets
7122        *  |GGGGG    B| in the border can confuse things
7123        *  |GGGGG    B|
7124        *  |         B|
7125        *  +----------+
7126        *
7127        *  +-----------+
7128        *  |AAAAAAAAA  | When the geometry widget is large, things are
7129        *  |GGGGGGGGGGB| clearer.
7130        *  |GGGGGGGGGGB|
7131        *  |GGGGGGGGGG |
7132        *  +-----------+
7133        */
7134 #define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */
7135       GtkRequisition requisition;
7136       int current_width, current_height;
7137
7138       _gtk_widget_override_size_request (geometry_info->widget,
7139                                          TEMPORARY_SIZE, TEMPORARY_SIZE,
7140                                          &current_width, &current_height);
7141       gtk_widget_get_preferred_size (widget,
7142                                      &requisition, NULL);
7143       _gtk_widget_restore_size_request (geometry_info->widget,
7144                                         current_width, current_height);
7145
7146       extra_width = requisition.width - TEMPORARY_SIZE;
7147       extra_height = requisition.height - TEMPORARY_SIZE;
7148
7149       if (extra_width < 0 || extra_width < 0)
7150         {
7151           g_warning("Toplevel size doesn't seem to directly depend on the "
7152                     "size of the geometry widget from gtk_window_set_geometry_hints(). "
7153                     "The geometry widget might not be in the window, or it might not "
7154                     "be packed into the window appropriately");
7155           extra_width = MAX(extra_width, 0);
7156           extra_height = MAX(extra_height, 0);
7157         }
7158 #undef TEMPORARY_SIZE
7159     }
7160
7161   /* We don't want to set GDK_HINT_POS in here, we just set it
7162    * in gtk_window_move_resize() when we want the position
7163    * honored.
7164    */
7165   
7166   if (*new_flags & GDK_HINT_BASE_SIZE)
7167     {
7168       new_geometry->base_width += extra_width;
7169       new_geometry->base_height += extra_height;
7170     }
7171   else
7172     {
7173       /* For simplicity, we always set the base hint, even when we
7174        * don't expect it to have any visible effect.
7175        * (Note: geometry_size_to_pixels() depends on this.)
7176        */
7177       *new_flags |= GDK_HINT_BASE_SIZE;
7178
7179       new_geometry->base_width = extra_width;
7180       new_geometry->base_height = extra_height;
7181
7182       /* As for X, if BASE_SIZE is not set but MIN_SIZE is set, then the
7183        * base size is the minimum size */
7184       if (*new_flags & GDK_HINT_MIN_SIZE)
7185         {
7186           if (new_geometry->min_width > 0)
7187             new_geometry->base_width += new_geometry->min_width;
7188           if (new_geometry->min_height > 0)
7189             new_geometry->base_height += new_geometry->min_height;
7190         }
7191     }
7192
7193   if (*new_flags & GDK_HINT_MIN_SIZE)
7194     {
7195       if (new_geometry->min_width < 0)
7196         new_geometry->min_width = requisition.width;
7197       else
7198         new_geometry->min_width = MAX (requisition.width, new_geometry->min_width + extra_width);
7199
7200       if (new_geometry->min_height < 0)
7201         new_geometry->min_height = requisition.height;
7202       else
7203         new_geometry->min_height = MAX (requisition.height, new_geometry->min_height + extra_height);
7204     }
7205   else
7206     {
7207       *new_flags |= GDK_HINT_MIN_SIZE;
7208       
7209       new_geometry->min_width = requisition.width;
7210       new_geometry->min_height = requisition.height;
7211     }
7212   
7213   if (*new_flags & GDK_HINT_MAX_SIZE)
7214     {
7215       if (new_geometry->max_width < 0)
7216         new_geometry->max_width = requisition.width;
7217       else
7218         new_geometry->max_width += extra_width;
7219
7220       if (new_geometry->max_height < 0)
7221         new_geometry->max_height = requisition.height;
7222       else
7223         new_geometry->max_height += extra_height;
7224     }
7225   else if (!priv->resizable)
7226     {
7227       *new_flags |= GDK_HINT_MAX_SIZE;
7228       
7229       new_geometry->max_width = requisition.width;
7230       new_geometry->max_height = requisition.height;
7231     }
7232
7233   *new_flags |= GDK_HINT_WIN_GRAVITY;
7234   new_geometry->win_gravity = priv->gravity;
7235 }
7236
7237 /***********************
7238  * Redrawing functions *
7239  ***********************/
7240
7241 static gboolean
7242 gtk_window_draw (GtkWidget *widget,
7243                  cairo_t   *cr)
7244 {
7245   GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
7246   GtkStyleContext *context;
7247   gboolean ret = FALSE;
7248
7249   context = gtk_widget_get_style_context (widget);
7250
7251   gtk_style_context_save (context);
7252
7253   if (!gtk_widget_get_app_paintable (widget))
7254     {
7255       GtkStateFlags state;
7256
7257       state = gtk_widget_get_state_flags (widget);
7258
7259       if (gtk_window_has_toplevel_focus (GTK_WINDOW (widget)))
7260         state |= GTK_STATE_FLAG_FOCUSED;
7261
7262       gtk_style_context_set_state (context, state);
7263       gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND);
7264       gtk_render_background (context, cr, 0, 0,
7265                              gtk_widget_get_allocated_width (widget),
7266                              gtk_widget_get_allocated_height (widget));
7267     }
7268
7269   gtk_style_context_restore (context);
7270
7271   if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
7272     ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
7273
7274   if (priv->grip_window != NULL &&
7275       gtk_cairo_should_draw_window (cr, priv->grip_window))
7276     {
7277       GdkRectangle rect;
7278
7279       gtk_style_context_save (context);
7280       cairo_save (cr);
7281
7282       gtk_cairo_transform_to_window (cr, widget, priv->grip_window);
7283       gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect);
7284
7285       gtk_style_context_add_class (context, GTK_STYLE_CLASS_GRIP);
7286       gtk_style_context_set_junction_sides (context, get_grip_junction (widget));
7287       gtk_render_handle (context, cr, 0, 0, rect.width, rect.height);
7288
7289       cairo_restore (cr);
7290       gtk_style_context_restore (context);
7291     }
7292
7293   return ret;
7294 }
7295
7296 /**
7297  * gtk_window_present:
7298  * @window: a #GtkWindow
7299  *
7300  * Presents a window to the user. This may mean raising the window
7301  * in the stacking order, deiconifying it, moving it to the current
7302  * desktop, and/or giving it the keyboard focus, possibly dependent
7303  * on the user's platform, window manager, and preferences.
7304  *
7305  * If @window is hidden, this function calls gtk_widget_show()
7306  * as well.
7307  * 
7308  * This function should be used when the user tries to open a window
7309  * that's already open. Say for example the preferences dialog is
7310  * currently open, and the user chooses Preferences from the menu
7311  * a second time; use gtk_window_present() to move the already-open dialog
7312  * where the user can see it.
7313  *
7314  * If you are calling this function in response to a user interaction,
7315  * it is preferable to use gtk_window_present_with_time().
7316  * 
7317  **/
7318 void
7319 gtk_window_present (GtkWindow *window)
7320 {
7321   gtk_window_present_with_time (window, GDK_CURRENT_TIME);
7322 }
7323
7324 /**
7325  * gtk_window_present_with_time:
7326  * @window: a #GtkWindow
7327  * @timestamp: the timestamp of the user interaction (typically a 
7328  *   button or key press event) which triggered this call
7329  *
7330  * Presents a window to the user in response to a user interaction.
7331  * If you need to present a window without a timestamp, use 
7332  * gtk_window_present(). See gtk_window_present() for details. 
7333  * 
7334  * Since: 2.8
7335  **/
7336 void
7337 gtk_window_present_with_time (GtkWindow *window,
7338                               guint32    timestamp)
7339 {
7340   GtkWidget *widget;
7341   GdkWindow *gdk_window;
7342
7343   g_return_if_fail (GTK_IS_WINDOW (window));
7344
7345   widget = GTK_WIDGET (window);
7346
7347   if (gtk_widget_get_visible (widget))
7348     {
7349       gdk_window = gtk_widget_get_window (widget);
7350
7351       g_assert (gdk_window != NULL);
7352
7353       gdk_window_show (gdk_window);
7354
7355       /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
7356       if (timestamp == GDK_CURRENT_TIME)
7357         {
7358 #ifdef GDK_WINDOWING_X11
7359           GdkDisplay *display;
7360
7361           display = gtk_widget_get_display (GTK_WIDGET (window));
7362           timestamp = gdk_x11_display_get_user_time (display);
7363 #else
7364           timestamp = gtk_get_current_event_time ();
7365 #endif
7366         }
7367
7368       gdk_window_focus (gdk_window, timestamp);
7369     }
7370   else
7371     {
7372       gtk_widget_show (widget);
7373     }
7374 }
7375
7376 /**
7377  * gtk_window_iconify:
7378  * @window: a #GtkWindow
7379  *
7380  * Asks to iconify (i.e. minimize) the specified @window. Note that
7381  * you shouldn't assume the window is definitely iconified afterward,
7382  * because other entities (e.g. the user or <link
7383  * linkend="gtk-X11-arch">window manager</link>) could deiconify it
7384  * again, or there may not be a window manager in which case
7385  * iconification isn't possible, etc. But normally the window will end
7386  * up iconified. Just don't write code that crashes if not.
7387  *
7388  * It's permitted to call this function before showing a window,
7389  * in which case the window will be iconified before it ever appears
7390  * onscreen.
7391  *
7392  * You can track iconification via the "window-state-event" signal
7393  * on #GtkWidget.
7394  * 
7395  **/
7396 void
7397 gtk_window_iconify (GtkWindow *window)
7398 {
7399   GtkWindowPrivate *priv;
7400   GtkWidget *widget;
7401   GdkWindow *toplevel;
7402   
7403   g_return_if_fail (GTK_IS_WINDOW (window));
7404
7405   priv = window->priv;
7406   widget = GTK_WIDGET (window);
7407
7408   priv->iconify_initially = TRUE;
7409
7410   toplevel = gtk_widget_get_window (widget);
7411
7412   if (toplevel != NULL)
7413     gdk_window_iconify (toplevel);
7414 }
7415
7416 /**
7417  * gtk_window_deiconify:
7418  * @window: a #GtkWindow
7419  *
7420  * Asks to deiconify (i.e. unminimize) the specified @window. Note
7421  * that you shouldn't assume the window is definitely deiconified
7422  * afterward, because other entities (e.g. the user or <link
7423  * linkend="gtk-X11-arch">window manager</link>) could iconify it
7424  * again before your code which assumes deiconification gets to run.
7425  *
7426  * You can track iconification via the "window-state-event" signal
7427  * on #GtkWidget.
7428  **/
7429 void
7430 gtk_window_deiconify (GtkWindow *window)
7431 {
7432   GtkWindowPrivate *priv;
7433   GtkWidget *widget;
7434   GdkWindow *toplevel;
7435   
7436   g_return_if_fail (GTK_IS_WINDOW (window));
7437
7438   priv = window->priv;
7439   widget = GTK_WIDGET (window);
7440
7441   priv->iconify_initially = FALSE;
7442
7443   toplevel = gtk_widget_get_window (widget);
7444
7445   if (toplevel != NULL)
7446     gdk_window_deiconify (toplevel);
7447 }
7448
7449 /**
7450  * gtk_window_stick:
7451  * @window: a #GtkWindow
7452  *
7453  * Asks to stick @window, which means that it will appear on all user
7454  * desktops. Note that you shouldn't assume the window is definitely
7455  * stuck afterward, because other entities (e.g. the user or <link
7456  * linkend="gtk-X11-arch">window manager</link>) could unstick it
7457  * again, and some window managers do not support sticking
7458  * windows. But normally the window will end up stuck. Just don't
7459  * write code that crashes if not.
7460  *
7461  * It's permitted to call this function before showing a window.
7462  *
7463  * You can track stickiness via the "window-state-event" signal
7464  * on #GtkWidget.
7465  * 
7466  **/
7467 void
7468 gtk_window_stick (GtkWindow *window)
7469 {
7470   GtkWindowPrivate *priv;
7471   GtkWidget *widget;
7472   GdkWindow *toplevel;
7473   
7474   g_return_if_fail (GTK_IS_WINDOW (window));
7475
7476   priv = window->priv;
7477   widget = GTK_WIDGET (window);
7478
7479   priv->stick_initially = TRUE;
7480
7481   toplevel = gtk_widget_get_window (widget);
7482
7483   if (toplevel != NULL)
7484     gdk_window_stick (toplevel);
7485 }
7486
7487 /**
7488  * gtk_window_unstick:
7489  * @window: a #GtkWindow
7490  *
7491  * Asks to unstick @window, which means that it will appear on only
7492  * one of the user's desktops. Note that you shouldn't assume the
7493  * window is definitely unstuck afterward, because other entities
7494  * (e.g. the user or <link linkend="gtk-X11-arch">window
7495  * manager</link>) could stick it again. But normally the window will
7496  * end up stuck. Just don't write code that crashes if not.
7497  *
7498  * You can track stickiness via the "window-state-event" signal
7499  * on #GtkWidget.
7500  * 
7501  **/
7502 void
7503 gtk_window_unstick (GtkWindow *window)
7504 {
7505   GtkWindowPrivate *priv;
7506   GtkWidget *widget;
7507   GdkWindow *toplevel;
7508   
7509   g_return_if_fail (GTK_IS_WINDOW (window));
7510
7511   priv = window->priv;
7512   widget = GTK_WIDGET (window);
7513
7514   priv->stick_initially = FALSE;
7515
7516   toplevel = gtk_widget_get_window (widget);
7517
7518   if (toplevel != NULL)
7519     gdk_window_unstick (toplevel);
7520 }
7521
7522 /**
7523  * gtk_window_maximize:
7524  * @window: a #GtkWindow
7525  *
7526  * Asks to maximize @window, so that it becomes full-screen. Note that
7527  * you shouldn't assume the window is definitely maximized afterward,
7528  * because other entities (e.g. the user or <link
7529  * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
7530  * again, and not all window managers support maximization. But
7531  * normally the window will end up maximized. Just don't write code
7532  * that crashes if not.
7533  *
7534  * It's permitted to call this function before showing a window,
7535  * in which case the window will be maximized when it appears onscreen
7536  * initially.
7537  *
7538  * You can track maximization via the "window-state-event" signal
7539  * on #GtkWidget.
7540  * 
7541  **/
7542 void
7543 gtk_window_maximize (GtkWindow *window)
7544 {
7545   GtkWindowPrivate *priv;
7546   GtkWidget *widget;
7547   GdkWindow *toplevel;
7548   
7549   g_return_if_fail (GTK_IS_WINDOW (window));
7550
7551   priv = window->priv;
7552   widget = GTK_WIDGET (window);
7553
7554   priv->maximize_initially = TRUE;
7555
7556   toplevel = gtk_widget_get_window (widget);
7557
7558   if (toplevel != NULL)
7559     gdk_window_maximize (toplevel);
7560 }
7561
7562 /**
7563  * gtk_window_unmaximize:
7564  * @window: a #GtkWindow
7565  *
7566  * Asks to unmaximize @window. Note that you shouldn't assume the
7567  * window is definitely unmaximized afterward, because other entities
7568  * (e.g. the user or <link linkend="gtk-X11-arch">window
7569  * manager</link>) could maximize it again, and not all window
7570  * managers honor requests to unmaximize. But normally the window will
7571  * end up unmaximized. Just don't write code that crashes if not.
7572  *
7573  * You can track maximization via the "window-state-event" signal
7574  * on #GtkWidget.
7575  * 
7576  **/
7577 void
7578 gtk_window_unmaximize (GtkWindow *window)
7579 {
7580   GtkWindowPrivate *priv;
7581   GtkWidget *widget;
7582   GdkWindow *toplevel;
7583   
7584   g_return_if_fail (GTK_IS_WINDOW (window));
7585
7586   priv = window->priv;
7587   widget = GTK_WIDGET (window);
7588
7589   priv->maximize_initially = FALSE;
7590
7591   toplevel = gtk_widget_get_window (widget);
7592
7593   if (toplevel != NULL)
7594     gdk_window_unmaximize (toplevel);
7595 }
7596
7597 /**
7598  * gtk_window_fullscreen:
7599  * @window: a #GtkWindow
7600  *
7601  * Asks to place @window in the fullscreen state. Note that you
7602  * shouldn't assume the window is definitely full screen afterward,
7603  * because other entities (e.g. the user or <link
7604  * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7605  * again, and not all window managers honor requests to fullscreen
7606  * windows. But normally the window will end up fullscreen. Just
7607  * don't write code that crashes if not.
7608  *
7609  * You can track the fullscreen state via the "window-state-event" signal
7610  * on #GtkWidget.
7611  * 
7612  * Since: 2.2
7613  **/
7614 void
7615 gtk_window_fullscreen (GtkWindow *window)
7616 {
7617   GtkWindowPrivate *priv;
7618   GtkWidget *widget;
7619   GdkWindow *toplevel;
7620
7621   g_return_if_fail (GTK_IS_WINDOW (window));
7622
7623   priv = window->priv;
7624   widget = GTK_WIDGET (window);
7625
7626   priv->fullscreen_initially = TRUE;
7627
7628   toplevel = gtk_widget_get_window (widget);
7629
7630   if (toplevel != NULL)
7631     gdk_window_fullscreen (toplevel);
7632 }
7633
7634 /**
7635  * gtk_window_unfullscreen:
7636  * @window: a #GtkWindow
7637  *
7638  * Asks to toggle off the fullscreen state for @window. Note that you
7639  * shouldn't assume the window is definitely not full screen
7640  * afterward, because other entities (e.g. the user or <link
7641  * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7642  * again, and not all window managers honor requests to unfullscreen
7643  * windows. But normally the window will end up restored to its normal
7644  * state. Just don't write code that crashes if not.
7645  *
7646  * You can track the fullscreen state via the "window-state-event" signal
7647  * on #GtkWidget.
7648  * 
7649  * Since: 2.2
7650  **/
7651 void
7652 gtk_window_unfullscreen (GtkWindow *window)
7653 {
7654   GtkWidget *widget;
7655   GdkWindow *toplevel;
7656   GtkWindowPrivate *priv;
7657
7658   g_return_if_fail (GTK_IS_WINDOW (window));
7659
7660   priv = window->priv;
7661   widget = GTK_WIDGET (window);
7662
7663   priv->fullscreen_initially = FALSE;
7664
7665   toplevel = gtk_widget_get_window (widget);
7666
7667   if (toplevel != NULL)
7668     gdk_window_unfullscreen (toplevel);
7669 }
7670
7671 /**
7672  * gtk_window_set_keep_above:
7673  * @window: a #GtkWindow
7674  * @setting: whether to keep @window above other windows
7675  *
7676  * Asks to keep @window above, so that it stays on top. Note that
7677  * you shouldn't assume the window is definitely above afterward,
7678  * because other entities (e.g. the user or <link
7679  * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
7680  * and not all window managers support keeping windows above. But
7681  * normally the window will end kept above. Just don't write code
7682  * that crashes if not.
7683  *
7684  * It's permitted to call this function before showing a window,
7685  * in which case the window will be kept above when it appears onscreen
7686  * initially.
7687  *
7688  * You can track the above state via the "window-state-event" signal
7689  * on #GtkWidget.
7690  *
7691  * Note that, according to the <ulink 
7692  * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window 
7693  * Manager Hints</ulink> specification, the above state is mainly meant 
7694  * for user preferences and should not be used by applications e.g. for 
7695  * drawing attention to their dialogs.
7696  *
7697  * Since: 2.4
7698  **/
7699 void
7700 gtk_window_set_keep_above (GtkWindow *window,
7701                            gboolean   setting)
7702 {
7703   GtkWidget *widget;
7704   GtkWindowPrivate *priv;
7705   GdkWindow *toplevel;
7706
7707   g_return_if_fail (GTK_IS_WINDOW (window));
7708
7709   priv = window->priv;
7710   widget = GTK_WIDGET (window);
7711
7712   priv->above_initially = setting != FALSE;
7713   if (setting)
7714     priv->below_initially = FALSE;
7715
7716   toplevel = gtk_widget_get_window (widget);
7717
7718   if (toplevel != NULL)
7719     gdk_window_set_keep_above (toplevel, setting);
7720 }
7721
7722 /**
7723  * gtk_window_set_keep_below:
7724  * @window: a #GtkWindow
7725  * @setting: whether to keep @window below other windows
7726  *
7727  * Asks to keep @window below, so that it stays in bottom. Note that
7728  * you shouldn't assume the window is definitely below afterward,
7729  * because other entities (e.g. the user or <link
7730  * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
7731  * and not all window managers support putting windows below. But
7732  * normally the window will be kept below. Just don't write code
7733  * that crashes if not.
7734  *
7735  * It's permitted to call this function before showing a window,
7736  * in which case the window will be kept below when it appears onscreen
7737  * initially.
7738  *
7739  * You can track the below state via the "window-state-event" signal
7740  * on #GtkWidget.
7741  *
7742  * Note that, according to the <ulink 
7743  * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window 
7744  * Manager Hints</ulink> specification, the above state is mainly meant 
7745  * for user preferences and should not be used by applications e.g. for 
7746  * drawing attention to their dialogs.
7747  *
7748  * Since: 2.4
7749  **/
7750 void
7751 gtk_window_set_keep_below (GtkWindow *window,
7752                            gboolean   setting)
7753 {
7754   GtkWidget *widget;
7755   GtkWindowPrivate *priv;
7756   GdkWindow *toplevel;
7757
7758   g_return_if_fail (GTK_IS_WINDOW (window));
7759
7760   priv = window->priv;
7761   widget = GTK_WIDGET (window);
7762
7763   priv->below_initially = setting != FALSE;
7764   if (setting)
7765     priv->above_initially = FALSE;
7766
7767   toplevel = gtk_widget_get_window (widget);
7768
7769   if (toplevel != NULL)
7770     gdk_window_set_keep_below (toplevel, setting);
7771 }
7772
7773 /**
7774  * gtk_window_set_resizable:
7775  * @window: a #GtkWindow
7776  * @resizable: %TRUE if the user can resize this window
7777  *
7778  * Sets whether the user can resize a window. Windows are user resizable
7779  * by default.
7780  **/
7781 void
7782 gtk_window_set_resizable (GtkWindow *window,
7783                           gboolean   resizable)
7784 {
7785   GtkWindowPrivate *priv;
7786
7787   g_return_if_fail (GTK_IS_WINDOW (window));
7788
7789   priv = window->priv;
7790
7791   resizable = (resizable != FALSE);
7792
7793   if (priv->resizable != resizable)
7794     {
7795       priv->resizable = (resizable != FALSE);
7796
7797       update_grip_visibility (window);
7798
7799       gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7800
7801       g_object_notify (G_OBJECT (window), "resizable");
7802     }
7803 }
7804
7805 /**
7806  * gtk_window_get_resizable:
7807  * @window: a #GtkWindow
7808  *
7809  * Gets the value set by gtk_window_set_resizable().
7810  *
7811  * Return value: %TRUE if the user can resize the window
7812  **/
7813 gboolean
7814 gtk_window_get_resizable (GtkWindow *window)
7815 {
7816   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7817
7818   return window->priv->resizable;
7819 }
7820
7821 /**
7822  * gtk_window_set_gravity:
7823  * @window: a #GtkWindow
7824  * @gravity: window gravity
7825  *
7826  * Window gravity defines the meaning of coordinates passed to
7827  * gtk_window_move(). See gtk_window_move() and #GdkGravity for
7828  * more details.
7829  *
7830  * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
7831  * typically "do what you mean."
7832  *
7833  **/
7834 void
7835 gtk_window_set_gravity (GtkWindow *window,
7836                         GdkGravity gravity)
7837 {
7838   GtkWindowPrivate *priv;
7839
7840   g_return_if_fail (GTK_IS_WINDOW (window));
7841
7842   priv = window->priv;
7843
7844   if (gravity != priv->gravity)
7845     {
7846       priv->gravity = gravity;
7847
7848       /* gtk_window_move_resize() will adapt gravity
7849        */
7850       gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7851
7852       g_object_notify (G_OBJECT (window), "gravity");
7853     }
7854 }
7855
7856 /**
7857  * gtk_window_get_gravity:
7858  * @window: a #GtkWindow
7859  *
7860  * Gets the value set by gtk_window_set_gravity().
7861  *
7862  * Return value: (transfer none): window gravity
7863  **/
7864 GdkGravity
7865 gtk_window_get_gravity (GtkWindow *window)
7866 {
7867   g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
7868
7869   return window->priv->gravity;
7870 }
7871
7872 /**
7873  * gtk_window_begin_resize_drag:
7874  * @window: a #GtkWindow
7875  * @button: mouse button that initiated the drag
7876  * @edge: position of the resize control
7877  * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7878  * @root_y: Y position where the user clicked to initiate the drag
7879  * @timestamp: timestamp from the click event that initiated the drag
7880  *
7881  * Starts resizing a window. This function is used if an application
7882  * has window resizing controls. When GDK can support it, the resize
7883  * will be done using the standard mechanism for the <link
7884  * linkend="gtk-X11-arch">window manager</link> or windowing
7885  * system. Otherwise, GDK will try to emulate window resizing,
7886  * potentially not all that well, depending on the windowing system.
7887  * 
7888  **/
7889 void
7890 gtk_window_begin_resize_drag  (GtkWindow    *window,
7891                                GdkWindowEdge edge,
7892                                gint          button,
7893                                gint          root_x,
7894                                gint          root_y,
7895                                guint32       timestamp)
7896 {
7897   GtkWindowPrivate *priv;
7898   GtkWidget *widget;
7899   GdkWindow *toplevel;
7900   
7901   g_return_if_fail (GTK_IS_WINDOW (window));
7902   widget = GTK_WIDGET (window);
7903   g_return_if_fail (gtk_widget_get_visible (widget));
7904
7905   priv = window->priv;
7906
7907   toplevel = gtk_widget_get_window (widget);
7908
7909   gdk_window_begin_resize_drag (toplevel,
7910                                 edge, button,
7911                                 root_x, root_y,
7912                                 timestamp);
7913 }
7914
7915 /**
7916  * gtk_window_begin_move_drag:
7917  * @window: a #GtkWindow
7918  * @button: mouse button that initiated the drag
7919  * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7920  * @root_y: Y position where the user clicked to initiate the drag
7921  * @timestamp: timestamp from the click event that initiated the drag
7922  *
7923  * Starts moving a window. This function is used if an application has
7924  * window movement grips. When GDK can support it, the window movement
7925  * will be done using the standard mechanism for the <link
7926  * linkend="gtk-X11-arch">window manager</link> or windowing
7927  * system. Otherwise, GDK will try to emulate window movement,
7928  * potentially not all that well, depending on the windowing system.
7929  * 
7930  **/
7931 void
7932 gtk_window_begin_move_drag  (GtkWindow *window,
7933                              gint       button,
7934                              gint       root_x,
7935                              gint       root_y,
7936                              guint32    timestamp)
7937 {
7938   GtkWindowPrivate *priv;
7939   GtkWidget *widget;
7940   GdkWindow *toplevel;
7941   
7942   g_return_if_fail (GTK_IS_WINDOW (window));
7943   widget = GTK_WIDGET (window);
7944   g_return_if_fail (gtk_widget_get_visible (widget));
7945
7946   priv = window->priv;
7947
7948   toplevel = gtk_widget_get_window (widget);
7949
7950   gdk_window_begin_move_drag (toplevel,
7951                               button,
7952                               root_x, root_y,
7953                               timestamp);
7954 }
7955
7956 /** 
7957  * gtk_window_set_screen:
7958  * @window: a #GtkWindow.
7959  * @screen: a #GdkScreen.
7960  *
7961  * Sets the #GdkScreen where the @window is displayed; if
7962  * the window is already mapped, it will be unmapped, and
7963  * then remapped on the new screen.
7964  *
7965  * Since: 2.2
7966  */
7967 void
7968 gtk_window_set_screen (GtkWindow *window,
7969                        GdkScreen *screen)
7970 {
7971   GtkWindowPrivate *priv;
7972   GtkWidget *widget;
7973   GdkScreen *previous_screen;
7974   gboolean was_mapped;
7975   
7976   g_return_if_fail (GTK_IS_WINDOW (window));
7977   g_return_if_fail (GDK_IS_SCREEN (screen));
7978
7979   priv = window->priv;
7980
7981   if (screen == priv->screen)
7982     return;
7983
7984   widget = GTK_WIDGET (window);
7985
7986   previous_screen = priv->screen;
7987   was_mapped = gtk_widget_get_mapped (widget);
7988
7989   if (was_mapped)
7990     gtk_widget_unmap (widget);
7991   if (gtk_widget_get_realized (widget))
7992     gtk_widget_unrealize (widget);
7993       
7994   gtk_window_free_key_hash (window);
7995   priv->screen = screen;
7996   gtk_widget_reset_rc_styles (widget);
7997   if (screen != previous_screen)
7998     {
7999       g_signal_handlers_disconnect_by_func (previous_screen,
8000                                             gtk_window_on_composited_changed, window);
8001       g_signal_connect (screen, "composited-changed", 
8002                         G_CALLBACK (gtk_window_on_composited_changed), window);
8003       
8004       _gtk_widget_propagate_screen_changed (widget, previous_screen);
8005       _gtk_widget_propagate_composited_changed (widget);
8006     }
8007   g_object_notify (G_OBJECT (window), "screen");
8008
8009   if (was_mapped)
8010     gtk_widget_map (widget);
8011 }
8012
8013 static void
8014 gtk_window_on_composited_changed (GdkScreen *screen,
8015                                   GtkWindow *window)
8016 {
8017   gtk_widget_queue_draw (GTK_WIDGET (window));
8018   
8019   _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
8020 }
8021
8022 static GdkScreen *
8023 gtk_window_check_screen (GtkWindow *window)
8024 {
8025   GtkWindowPrivate *priv = window->priv;
8026
8027   if (priv->screen)
8028     return priv->screen;
8029   else
8030     {
8031       g_warning ("Screen for GtkWindow not set; you must always set\n"
8032                  "a screen for a GtkWindow before using the window");
8033       return NULL;
8034     }
8035 }
8036
8037 /**
8038  * gtk_window_get_screen:
8039  * @window: a #GtkWindow.
8040  *
8041  * Returns the #GdkScreen associated with @window.
8042  *
8043  * Return value: (transfer none): a #GdkScreen.
8044  *
8045  * Since: 2.2
8046  */
8047 GdkScreen*
8048 gtk_window_get_screen (GtkWindow *window)
8049 {
8050   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
8051
8052   return window->priv->screen;
8053 }
8054
8055 /**
8056  * gtk_window_is_active:
8057  * @window: a #GtkWindow
8058  * 
8059  * Returns whether the window is part of the current active toplevel.
8060  * (That is, the toplevel window receiving keystrokes.)
8061  * The return value is %TRUE if the window is active toplevel
8062  * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
8063  * You might use this function if you wanted to draw a widget
8064  * differently in an active window from a widget in an inactive window.
8065  * See gtk_window_has_toplevel_focus()
8066  * 
8067  * Return value: %TRUE if the window part of the current active window.
8068  *
8069  * Since: 2.4
8070  **/
8071 gboolean
8072 gtk_window_is_active (GtkWindow *window)
8073 {
8074   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8075
8076   return window->priv->is_active;
8077 }
8078
8079 /**
8080  * gtk_window_has_toplevel_focus:
8081  * @window: a #GtkWindow
8082  * 
8083  * Returns whether the input focus is within this GtkWindow.
8084  * For real toplevel windows, this is identical to gtk_window_is_active(),
8085  * but for embedded windows, like #GtkPlug, the results will differ.
8086  * 
8087  * Return value: %TRUE if the input focus is within this GtkWindow
8088  *
8089  * Since: 2.4
8090  **/
8091 gboolean
8092 gtk_window_has_toplevel_focus (GtkWindow *window)
8093 {
8094   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8095
8096   return window->priv->has_toplevel_focus;
8097 }
8098
8099 G_DEFINE_TYPE (GtkWindowGroup, gtk_window_group, G_TYPE_OBJECT)
8100
8101 static void
8102 gtk_window_group_init (GtkWindowGroup *group)
8103 {
8104   group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
8105                                              GTK_TYPE_WINDOW_GROUP,
8106                                              GtkWindowGroupPrivate);
8107 }
8108
8109 static void
8110 gtk_window_group_class_init (GtkWindowGroupClass *klass)
8111 {
8112   g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate));
8113 }
8114
8115 /**
8116  * gtk_window_group_new:
8117  * 
8118  * Creates a new #GtkWindowGroup object. Grabs added with
8119  * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
8120  * 
8121  * Return value: a new #GtkWindowGroup. 
8122  **/
8123 GtkWindowGroup *
8124 gtk_window_group_new (void)
8125 {
8126   return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
8127 }
8128
8129 static void
8130 window_group_cleanup_grabs (GtkWindowGroup *group,
8131                             GtkWindow      *window)
8132 {
8133   GtkWindowGroupPrivate *priv;
8134   GtkDeviceGrabInfo *info;
8135   GSList *tmp_list;
8136   GSList *to_remove = NULL;
8137
8138   priv = group->priv;
8139
8140   tmp_list = priv->grabs;
8141   while (tmp_list)
8142     {
8143       if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
8144         to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
8145       tmp_list = tmp_list->next;
8146     }
8147
8148   while (to_remove)
8149     {
8150       gtk_grab_remove (to_remove->data);
8151       g_object_unref (to_remove->data);
8152       to_remove = g_slist_delete_link (to_remove, to_remove);
8153     }
8154
8155   tmp_list = priv->device_grabs;
8156
8157   while (tmp_list)
8158     {
8159       info = tmp_list->data;
8160
8161       if (gtk_widget_get_toplevel (info->widget) == (GtkWidget *) window)
8162         to_remove = g_slist_prepend (to_remove, info);
8163
8164       tmp_list = tmp_list->next;
8165     }
8166
8167   while (to_remove)
8168     {
8169       info = to_remove->data;
8170
8171       gtk_device_grab_remove (info->widget, info->device);
8172       to_remove = g_slist_delete_link (to_remove, to_remove);
8173     }
8174 }
8175
8176 /**
8177  * gtk_window_group_add_window:
8178  * @window_group: a #GtkWindowGroup
8179  * @window: the #GtkWindow to add
8180  * 
8181  * Adds a window to a #GtkWindowGroup. 
8182  **/
8183 void
8184 gtk_window_group_add_window (GtkWindowGroup *window_group,
8185                              GtkWindow      *window)
8186 {
8187   GtkWindowPrivate *priv;
8188
8189   g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8190   g_return_if_fail (GTK_IS_WINDOW (window));
8191
8192   priv = window->priv;
8193
8194   if (priv->group != window_group)
8195     {
8196       g_object_ref (window);
8197       g_object_ref (window_group);
8198
8199       if (priv->group)
8200         gtk_window_group_remove_window (priv->group, window);
8201       else
8202         window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
8203
8204       priv->group = window_group;
8205
8206       g_object_unref (window);
8207     }
8208 }
8209
8210 /**
8211  * gtk_window_group_remove_window:
8212  * @window_group: a #GtkWindowGroup
8213  * @window: the #GtkWindow to remove
8214  * 
8215  * Removes a window from a #GtkWindowGroup.
8216  **/
8217 void
8218 gtk_window_group_remove_window (GtkWindowGroup *window_group,
8219                                 GtkWindow      *window)
8220 {
8221   GtkWindowPrivate *priv;
8222
8223   g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
8224   g_return_if_fail (GTK_IS_WINDOW (window));
8225   priv = window->priv;
8226   g_return_if_fail (priv->group == window_group);
8227
8228   g_object_ref (window);
8229
8230   window_group_cleanup_grabs (window_group, window);
8231   priv->group = NULL;
8232
8233   g_object_unref (window_group);
8234   g_object_unref (window);
8235 }
8236
8237 /**
8238  * gtk_window_group_list_windows:
8239  * @window_group: a #GtkWindowGroup
8240  *
8241  * Returns a list of the #GtkWindows that belong to @window_group.
8242  *
8243  * Returns: (element-type GtkWidget) (transfer container): A newly-allocated list of
8244  *   windows inside the group.
8245  *
8246  * Since: 2.14
8247  **/
8248 GList *
8249 gtk_window_group_list_windows (GtkWindowGroup *window_group)
8250 {
8251   GList *toplevels, *toplevel, *group_windows;
8252
8253   g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8254
8255   group_windows = NULL;
8256   toplevels = gtk_window_list_toplevels ();
8257
8258   for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
8259     {
8260       GtkWindow *window = toplevel->data;
8261
8262       if (window_group == window->priv->group)
8263         group_windows = g_list_prepend (group_windows, window);
8264     }
8265
8266   return g_list_reverse (group_windows);
8267 }
8268
8269 /**
8270  * gtk_window_get_group:
8271  * @window: (allow-none): a #GtkWindow, or %NULL
8272  *
8273  * Returns the group for @window or the default group, if
8274  * @window is %NULL or if @window does not have an explicit
8275  * window group.
8276  *
8277  * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
8278  *
8279  * Since: 2.10
8280  */
8281 GtkWindowGroup *
8282 gtk_window_get_group (GtkWindow *window)
8283 {
8284   if (window && window->priv->group)
8285     return window->priv->group;
8286   else
8287     {
8288       static GtkWindowGroup *default_group = NULL;
8289
8290       if (!default_group)
8291         default_group = gtk_window_group_new ();
8292
8293       return default_group;
8294     }
8295 }
8296
8297 /**
8298  * gtk_window_has_group:
8299  * @window: a #GtkWindow
8300  *
8301  * Returns whether @window has an explicit window group.
8302  *
8303  * Return value: %TRUE if @window has an explicit window group.
8304  *
8305  * Since 2.22
8306  **/
8307 gboolean
8308 gtk_window_has_group (GtkWindow *window)
8309 {
8310   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8311
8312   return window->priv->group != NULL;
8313 }
8314
8315 /**
8316  * gtk_window_group_get_current_grab:
8317  * @window_group: a #GtkWindowGroup
8318  *
8319  * Gets the current grab widget of the given group,
8320  * see gtk_grab_add().
8321  *
8322  * Returns: the current grab widget of the group
8323  *
8324  * Since: 2.22
8325  */
8326 GtkWidget *
8327 gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
8328 {
8329   g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8330
8331   if (window_group->priv->grabs)
8332     return GTK_WIDGET (window_group->priv->grabs->data);
8333   return NULL;
8334 }
8335
8336 void
8337 _gtk_window_group_add_grab (GtkWindowGroup *window_group,
8338                             GtkWidget      *widget)
8339 {
8340   GtkWindowGroupPrivate *priv;
8341
8342   priv = window_group->priv;
8343   priv->grabs = g_slist_prepend (priv->grabs, widget);
8344 }
8345
8346 void
8347 _gtk_window_group_remove_grab (GtkWindowGroup *window_group,
8348                                GtkWidget      *widget)
8349 {
8350   GtkWindowGroupPrivate *priv;
8351
8352   priv = window_group->priv;
8353   priv->grabs = g_slist_remove (priv->grabs, widget);
8354 }
8355
8356
8357 void
8358 _gtk_window_group_add_device_grab (GtkWindowGroup *window_group,
8359                                    GtkWidget      *widget,
8360                                    GdkDevice      *device,
8361                                    gboolean        block_others)
8362 {
8363   GtkWindowGroupPrivate *priv;
8364   GtkDeviceGrabInfo *info;
8365
8366   priv = window_group->priv;
8367
8368   info = g_slice_new0 (GtkDeviceGrabInfo);
8369   info->widget = widget;
8370   info->device = device;
8371   info->block_others = block_others;
8372
8373   priv->device_grabs = g_slist_prepend (priv->device_grabs, info);
8374 }
8375
8376 void
8377 _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group,
8378                                       GtkWidget      *widget,
8379                                       GdkDevice      *device)
8380 {
8381   GtkWindowGroupPrivate *priv;
8382   GtkDeviceGrabInfo *info;
8383   GSList *list, *node = NULL;
8384   GdkDevice *other_device;
8385
8386   priv = window_group->priv;
8387   other_device = gdk_device_get_associated_device (device);
8388   list = priv->device_grabs;
8389
8390   while (list)
8391     {
8392       info = list->data;
8393
8394       if (info->widget == widget &&
8395           (info->device == device ||
8396            info->device == other_device))
8397         {
8398           node = list;
8399           break;
8400         }
8401
8402       list = list->next;
8403     }
8404
8405   if (node)
8406     {
8407       info = node->data;
8408
8409       priv->device_grabs = g_slist_delete_link (priv->device_grabs, node);
8410       g_slice_free (GtkDeviceGrabInfo, info);
8411     }
8412 }
8413
8414 /**
8415  * gtk_window_group_get_current_device_grab:
8416  * @window_group: a #GtkWindowGroup
8417  * @device: a #GdkDevice
8418  *
8419  * Returns the current grab widget for @device, or %NULL if none.
8420  *
8421  * Returns: The grab widget, or %NULL
8422  *
8423  * Since: 3.0
8424  */
8425 GtkWidget *
8426 gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
8427                                           GdkDevice      *device)
8428 {
8429   GtkWindowGroupPrivate *priv;
8430   GtkDeviceGrabInfo *info;
8431   GdkDevice *other_device;
8432   GSList *list;
8433
8434   g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
8435   g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8436
8437   priv = window_group->priv;
8438   list = priv->device_grabs;
8439   other_device = gdk_device_get_associated_device (device);
8440
8441   while (list)
8442     {
8443       info = list->data;
8444       list = list->next;
8445
8446       if (info->device == device ||
8447           info->device == other_device)
8448         return info->widget;
8449     }
8450
8451   return NULL;
8452 }
8453
8454 gboolean
8455 _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group,
8456                                                 GtkWidget      *widget,
8457                                                 GdkDevice      *device)
8458 {
8459   GtkWindowGroupPrivate *priv;
8460   GtkDeviceGrabInfo *info;
8461   GdkDevice *other_device;
8462   GSList *list;
8463
8464   priv = window_group->priv;
8465   other_device = gdk_device_get_associated_device (device);
8466   list = priv->device_grabs;
8467
8468   while (list)
8469     {
8470       info = list->data;
8471       list = list->next;
8472
8473       /* Look for blocking grabs on other device pairs
8474        * that have the passed widget within the GTK+ grab.
8475        */
8476       if (info->block_others &&
8477           info->device != device &&
8478           info->device != other_device &&
8479           (info->widget == widget ||
8480            gtk_widget_is_ancestor (widget, info->widget)))
8481         return TRUE;
8482     }
8483
8484   return FALSE;
8485 }
8486
8487 /*
8488   Derived from XParseGeometry() in XFree86  
8489
8490   Copyright 1985, 1986, 1987,1998  The Open Group
8491
8492   All Rights Reserved.
8493
8494   The above copyright notice and this permission notice shall be included
8495   in all copies or substantial portions of the Software.
8496
8497   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8498   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8499   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8500   IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
8501   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
8502   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
8503   OTHER DEALINGS IN THE SOFTWARE.
8504
8505   Except as contained in this notice, the name of The Open Group shall
8506   not be used in advertising or otherwise to promote the sale, use or
8507   other dealings in this Software without prior written authorization
8508   from The Open Group.
8509 */
8510
8511
8512 /*
8513  *    XParseGeometry parses strings of the form
8514  *   "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
8515  *   width, height, xoffset, and yoffset are unsigned integers.
8516  *   Example:  "=80x24+300-49"
8517  *   The equal sign is optional.
8518  *   It returns a bitmask that indicates which of the four values
8519  *   were actually found in the string.  For each value found,
8520  *   the corresponding argument is updated;  for each value
8521  *   not found, the corresponding argument is left unchanged. 
8522  */
8523
8524 /* The following code is from Xlib, and is minimally modified, so we
8525  * can track any upstream changes if required.  Don't change this
8526  * code. Or if you do, put in a huge comment marking which thing
8527  * changed.
8528  */
8529
8530 static int
8531 read_int (gchar   *string,
8532           gchar  **next)
8533 {
8534   int result = 0;
8535   int sign = 1;
8536   
8537   if (*string == '+')
8538     string++;
8539   else if (*string == '-')
8540     {
8541       string++;
8542       sign = -1;
8543     }
8544
8545   for (; (*string >= '0') && (*string <= '9'); string++)
8546     {
8547       result = (result * 10) + (*string - '0');
8548     }
8549
8550   *next = string;
8551
8552   if (sign >= 0)
8553     return (result);
8554   else
8555     return (-result);
8556 }
8557
8558 /* 
8559  * Bitmask returned by XParseGeometry().  Each bit tells if the corresponding
8560  * value (x, y, width, height) was found in the parsed string.
8561  */
8562 #define NoValue         0x0000
8563 #define XValue          0x0001
8564 #define YValue          0x0002
8565 #define WidthValue      0x0004
8566 #define HeightValue     0x0008
8567 #define AllValues       0x000F
8568 #define XNegative       0x0010
8569 #define YNegative       0x0020
8570
8571 /* Try not to reformat/modify, so we can compare/sync with X sources */
8572 static int
8573 gtk_XParseGeometry (const char   *string,
8574                     int          *x,
8575                     int          *y,
8576                     unsigned int *width,   
8577                     unsigned int *height)  
8578 {
8579   int mask = NoValue;
8580   char *strind;
8581   unsigned int tempWidth, tempHeight;
8582   int tempX, tempY;
8583   char *nextCharacter;
8584
8585   /* These initializations are just to silence gcc */
8586   tempWidth = 0;
8587   tempHeight = 0;
8588   tempX = 0;
8589   tempY = 0;
8590   
8591   if ( (string == NULL) || (*string == '\0')) return(mask);
8592   if (*string == '=')
8593     string++;  /* ignore possible '=' at beg of geometry spec */
8594
8595   strind = (char *)string;
8596   if (*strind != '+' && *strind != '-' && *strind != 'x') {
8597     tempWidth = read_int(strind, &nextCharacter);
8598     if (strind == nextCharacter) 
8599       return (0);
8600     strind = nextCharacter;
8601     mask |= WidthValue;
8602   }
8603
8604   if (*strind == 'x' || *strind == 'X') {       
8605     strind++;
8606     tempHeight = read_int(strind, &nextCharacter);
8607     if (strind == nextCharacter)
8608       return (0);
8609     strind = nextCharacter;
8610     mask |= HeightValue;
8611   }
8612
8613   if ((*strind == '+') || (*strind == '-')) {
8614     if (*strind == '-') {
8615       strind++;
8616       tempX = -read_int(strind, &nextCharacter);
8617       if (strind == nextCharacter)
8618         return (0);
8619       strind = nextCharacter;
8620       mask |= XNegative;
8621
8622     }
8623     else
8624       { strind++;
8625       tempX = read_int(strind, &nextCharacter);
8626       if (strind == nextCharacter)
8627         return(0);
8628       strind = nextCharacter;
8629       }
8630     mask |= XValue;
8631     if ((*strind == '+') || (*strind == '-')) {
8632       if (*strind == '-') {
8633         strind++;
8634         tempY = -read_int(strind, &nextCharacter);
8635         if (strind == nextCharacter)
8636           return(0);
8637         strind = nextCharacter;
8638         mask |= YNegative;
8639
8640       }
8641       else
8642         {
8643           strind++;
8644           tempY = read_int(strind, &nextCharacter);
8645           if (strind == nextCharacter)
8646             return(0);
8647           strind = nextCharacter;
8648         }
8649       mask |= YValue;
8650     }
8651   }
8652         
8653   /* If strind isn't at the end of the string the it's an invalid
8654                 geometry specification. */
8655
8656   if (*strind != '\0') return (0);
8657
8658   if (mask & XValue)
8659     *x = tempX;
8660   if (mask & YValue)
8661     *y = tempY;
8662   if (mask & WidthValue)
8663     *width = tempWidth;
8664   if (mask & HeightValue)
8665     *height = tempHeight;
8666   return (mask);
8667 }
8668
8669 /**
8670  * gtk_window_parse_geometry:
8671  * @window: a #GtkWindow
8672  * @geometry: geometry string
8673  * 
8674  * Parses a standard X Window System geometry string - see the
8675  * manual page for X (type 'man X') for details on this.
8676  * gtk_window_parse_geometry() does work on all GTK+ ports
8677  * including Win32 but is primarily intended for an X environment.
8678  *
8679  * If either a size or a position can be extracted from the
8680  * geometry string, gtk_window_parse_geometry() returns %TRUE
8681  * and calls gtk_window_set_default_size() and/or gtk_window_move()
8682  * to resize/move the window.
8683  *
8684  * If gtk_window_parse_geometry() returns %TRUE, it will also
8685  * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
8686  * indicating to the window manager that the size/position of
8687  * the window was user-specified. This causes most window
8688  * managers to honor the geometry.
8689  *
8690  * Note that for gtk_window_parse_geometry() to work as expected, it has
8691  * to be called when the window has its "final" size, i.e. after calling
8692  * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
8693  * on the window.
8694  * |[
8695  * #include <gtk/gtk.h>
8696  *    
8697  * static void
8698  * fill_with_content (GtkWidget *vbox)
8699  * {
8700  *   /&ast; fill with content... &ast;/
8701  * }
8702  *    
8703  * int
8704  * main (int argc, char *argv[])
8705  * {
8706  *   GtkWidget *window, *vbox;
8707  *   GdkGeometry size_hints = {
8708  *     100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST  
8709  *   };
8710  *    
8711  *   gtk_init (&argc, &argv);
8712  *   
8713  *   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8714  *   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
8715  *   
8716  *   gtk_container_add (GTK_CONTAINER (window), vbox);
8717  *   fill_with_content (vbox);
8718  *   gtk_widget_show_all (vbox);
8719  *   
8720  *   gtk_window_set_geometry_hints (GTK_WINDOW (window),
8721  *                                  window,
8722  *                                  &size_hints,
8723  *                                  GDK_HINT_MIN_SIZE | 
8724  *                                  GDK_HINT_BASE_SIZE | 
8725  *                                  GDK_HINT_RESIZE_INC);
8726  *   
8727  *   if (argc &gt; 1)
8728  *     {
8729  *       if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
8730  *         fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
8731  *     }
8732  *    
8733  *   gtk_widget_show_all (window);
8734  *   gtk_main ();
8735  *    
8736  *   return 0;
8737  * }
8738  * ]|
8739  *
8740  * Return value: %TRUE if string was parsed successfully
8741  **/
8742 gboolean
8743 gtk_window_parse_geometry (GtkWindow   *window,
8744                            const gchar *geometry)
8745 {
8746   gint result, x = 0, y = 0;
8747   guint w, h;
8748   GtkWidget *child;
8749   GdkGravity grav;
8750   gboolean size_set, pos_set;
8751   GdkScreen *screen;
8752   
8753   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8754   g_return_val_if_fail (geometry != NULL, FALSE);
8755
8756   child = gtk_bin_get_child (GTK_BIN (window));
8757   if (!child || !gtk_widget_get_visible (child))
8758     g_warning ("gtk_window_parse_geometry() called on a window with no "
8759                "visible children; the window should be set up before "
8760                "gtk_window_parse_geometry() is called.");
8761
8762   screen = gtk_window_check_screen (window);
8763   
8764   result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
8765
8766   size_set = FALSE;
8767   if ((result & WidthValue) || (result & HeightValue))
8768     {
8769       gtk_window_set_default_size_internal (window, 
8770                                             TRUE, result & WidthValue ? w : -1,
8771                                             TRUE, result & HeightValue ? h : -1, 
8772                                             TRUE);
8773       size_set = TRUE;
8774     }
8775
8776   gtk_window_get_size (window, (gint *)&w, (gint *)&h);
8777   
8778   grav = GDK_GRAVITY_NORTH_WEST;
8779
8780   if ((result & XNegative) && (result & YNegative))
8781     grav = GDK_GRAVITY_SOUTH_EAST;
8782   else if (result & XNegative)
8783     grav = GDK_GRAVITY_NORTH_EAST;
8784   else if (result & YNegative)
8785     grav = GDK_GRAVITY_SOUTH_WEST;
8786
8787   if ((result & XValue) == 0)
8788     x = 0;
8789
8790   if ((result & YValue) == 0)
8791     y = 0;
8792
8793   if (grav == GDK_GRAVITY_SOUTH_WEST ||
8794       grav == GDK_GRAVITY_SOUTH_EAST)
8795     y = gdk_screen_get_height (screen) - h + y;
8796
8797   if (grav == GDK_GRAVITY_SOUTH_EAST ||
8798       grav == GDK_GRAVITY_NORTH_EAST)
8799     x = gdk_screen_get_width (screen) - w + x;
8800
8801   /* we don't let you put a window offscreen; maybe some people would
8802    * prefer to be able to, but it's kind of a bogus thing to do.
8803    */
8804   if (y < 0)
8805     y = 0;
8806
8807   if (x < 0)
8808     x = 0;
8809
8810   pos_set = FALSE;
8811   if ((result & XValue) || (result & YValue))
8812     {
8813       gtk_window_set_gravity (window, grav);
8814       gtk_window_move (window, x, y);
8815       pos_set = TRUE;
8816     }
8817
8818   if (size_set || pos_set)
8819     {
8820       /* Set USSize, USPosition hints */
8821       GtkWindowGeometryInfo *info;
8822
8823       info = gtk_window_get_geometry_info (window, TRUE);
8824
8825       if (pos_set)
8826         info->mask |= GDK_HINT_USER_POS;
8827       if (size_set)
8828         info->mask |= GDK_HINT_USER_SIZE;
8829     }
8830   
8831   return result != 0;
8832 }
8833
8834 static void
8835 gtk_window_mnemonic_hash_foreach (guint      keyval,
8836                                   GSList    *targets,
8837                                   gpointer   data)
8838 {
8839   struct {
8840     GtkWindow *window;
8841     GtkWindowKeysForeachFunc func;
8842     gpointer func_data;
8843   } *info = data;
8844
8845   (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data);
8846 }
8847
8848 void
8849 _gtk_window_keys_foreach (GtkWindow                *window,
8850                           GtkWindowKeysForeachFunc func,
8851                           gpointer                 func_data)
8852 {
8853   GSList *groups;
8854   GtkMnemonicHash *mnemonic_hash;
8855
8856   struct {
8857     GtkWindow *window;
8858     GtkWindowKeysForeachFunc func;
8859     gpointer func_data;
8860   } info;
8861
8862   info.window = window;
8863   info.func = func;
8864   info.func_data = func_data;
8865
8866   mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
8867   if (mnemonic_hash)
8868     _gtk_mnemonic_hash_foreach (mnemonic_hash,
8869                                 gtk_window_mnemonic_hash_foreach, &info);
8870
8871   groups = gtk_accel_groups_from_object (G_OBJECT (window));
8872   while (groups)
8873     {
8874       GtkAccelGroup *group = groups->data;
8875       gint i;
8876
8877       for (i = 0; i < group->priv->n_accels; i++)
8878         {
8879           GtkAccelKey *key = &group->priv->priv_accels[i].key;
8880           
8881           if (key->accel_key)
8882             (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
8883         }
8884       
8885       groups = groups->next;
8886     }
8887 }
8888
8889 static void
8890 gtk_window_keys_changed (GtkWindow *window)
8891 {
8892   gtk_window_free_key_hash (window);
8893   gtk_window_get_key_hash (window);
8894 }
8895
8896 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
8897
8898 struct _GtkWindowKeyEntry
8899 {
8900   guint keyval;
8901   guint modifiers;
8902   guint is_mnemonic : 1;
8903 };
8904
8905 static void 
8906 window_key_entry_destroy (gpointer data)
8907 {
8908   g_slice_free (GtkWindowKeyEntry, data);
8909 }
8910
8911 static void
8912 add_to_key_hash (GtkWindow      *window,
8913                  guint           keyval,
8914                  GdkModifierType modifiers,
8915                  gboolean        is_mnemonic,
8916                  gpointer        data)
8917 {
8918   GtkKeyHash *key_hash = data;
8919
8920   GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
8921
8922   entry->keyval = keyval;
8923   entry->modifiers = modifiers;
8924   entry->is_mnemonic = is_mnemonic;
8925
8926   /* GtkAccelGroup stores lowercased accelerators. To deal
8927    * with this, if <Shift> was specified, uppercase.
8928    */
8929   if (modifiers & GDK_SHIFT_MASK)
8930     {
8931       if (keyval == GDK_KEY_Tab)
8932         keyval = GDK_KEY_ISO_Left_Tab;
8933       else
8934         keyval = gdk_keyval_to_upper (keyval);
8935     }
8936   
8937   _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
8938 }
8939
8940 static GtkKeyHash *
8941 gtk_window_get_key_hash (GtkWindow *window)
8942 {
8943   GdkScreen *screen = gtk_window_check_screen (window);
8944   GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
8945   
8946   if (key_hash)
8947     return key_hash;
8948   
8949   key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
8950                                 (GDestroyNotify)window_key_entry_destroy);
8951   _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
8952   g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
8953
8954   return key_hash;
8955 }
8956
8957 static void
8958 gtk_window_free_key_hash (GtkWindow *window)
8959 {
8960   GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
8961   if (key_hash)
8962     {
8963       _gtk_key_hash_free (key_hash);
8964       g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
8965     }
8966 }
8967
8968 /**
8969  * gtk_window_activate_key:
8970  * @window:  a #GtkWindow
8971  * @event:   a #GdkEventKey
8972  *
8973  * Activates mnemonics and accelerators for this #GtkWindow. This is normally
8974  * called by the default ::key_press_event handler for toplevel windows,
8975  * however in some cases it may be useful to call this directly when
8976  * overriding the standard key handling for a toplevel window.
8977  *
8978  * Return value: %TRUE if a mnemonic or accelerator was found and activated.
8979  *
8980  * Since: 2.4
8981  */
8982 gboolean
8983 gtk_window_activate_key (GtkWindow   *window,
8984                          GdkEventKey *event)
8985 {
8986   GtkKeyHash *key_hash;
8987   GtkWindowKeyEntry *found_entry = NULL;
8988   gboolean enable_mnemonics;
8989   gboolean enable_accels;
8990
8991   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8992   g_return_val_if_fail (event != NULL, FALSE);
8993
8994   key_hash = gtk_window_get_key_hash (window);
8995
8996   if (key_hash)
8997     {
8998       GSList *tmp_list;
8999       GSList *entries = _gtk_key_hash_lookup (key_hash,
9000                                               event->hardware_keycode,
9001                                               event->state,
9002                                               gtk_accelerator_get_default_mod_mask (),
9003                                               event->group);
9004
9005       g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
9006                     "gtk-enable-mnemonics", &enable_mnemonics,
9007                     "gtk-enable-accels", &enable_accels,
9008                     NULL);
9009
9010       for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
9011         {
9012           GtkWindowKeyEntry *entry = tmp_list->data;
9013           if (entry->is_mnemonic)
9014             {
9015               if (enable_mnemonics)
9016                 {
9017                   found_entry = entry;
9018                   break;
9019                 }
9020             }
9021           else 
9022             {
9023               if (enable_accels && !found_entry)
9024                 {
9025                   found_entry = entry;
9026                 }
9027             }
9028         }
9029
9030       g_slist_free (entries);
9031     }
9032
9033   if (found_entry)
9034     {
9035       if (found_entry->is_mnemonic)
9036         {
9037           if (enable_mnemonics)
9038             return gtk_window_mnemonic_activate (window, found_entry->keyval,
9039                                                  found_entry->modifiers);
9040         }
9041       else
9042         {
9043           if (enable_accels)
9044             return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
9045                                               found_entry->modifiers);
9046         }
9047     }
9048
9049   return FALSE;
9050 }
9051
9052 static void
9053 window_update_has_focus (GtkWindow *window)
9054 {
9055   GtkWindowPrivate *priv = window->priv;
9056   GtkWidget *widget = GTK_WIDGET (window);
9057   gboolean has_focus = priv->has_toplevel_focus && priv->is_active;
9058
9059   if (has_focus != priv->has_focus)
9060     {
9061       priv->has_focus = has_focus;
9062
9063       if (has_focus)
9064         {
9065           if (priv->focus_widget &&
9066               priv->focus_widget != widget &&
9067               !gtk_widget_has_focus (priv->focus_widget))
9068             do_focus_change (priv->focus_widget, TRUE);
9069         }
9070       else
9071         {
9072           if (priv->focus_widget &&
9073               priv->focus_widget != widget &&
9074               gtk_widget_has_focus (priv->focus_widget))
9075             do_focus_change (priv->focus_widget, FALSE);
9076         }
9077     }
9078 }
9079
9080 /**
9081  * _gtk_window_set_is_active:
9082  * @window: a #GtkWindow
9083  * @is_active: %TRUE if the window is in the currently active toplevel
9084  * 
9085  * Internal function that sets whether the #GtkWindow is part
9086  * of the currently active toplevel window (taking into account inter-process
9087  * embedding.)
9088  **/
9089 void
9090 _gtk_window_set_is_active (GtkWindow *window,
9091                            gboolean   is_active)
9092 {
9093   GtkWindowPrivate *priv;
9094
9095   g_return_if_fail (GTK_IS_WINDOW (window));
9096
9097   priv = window->priv;
9098
9099   is_active = is_active != FALSE;
9100
9101   if (is_active != priv->is_active)
9102     {
9103       priv->is_active = is_active;
9104       window_update_has_focus (window);
9105
9106       g_object_notify (G_OBJECT (window), "is-active");
9107     }
9108 }
9109
9110 /**
9111  * _gtk_window_set_is_toplevel:
9112  * @window: a #GtkWindow
9113  * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
9114  * child of the root window); %FALSE if it is not (for example, for an
9115  * in-process, parented GtkPlug)
9116  *
9117  * Internal function used by #GtkPlug when it gets parented/unparented by a
9118  * #GtkSocket.  This keeps the @window's #GTK_TOPLEVEL flag in sync with the
9119  * global list of toplevel windows.
9120  */
9121 void
9122 _gtk_window_set_is_toplevel (GtkWindow *window,
9123                              gboolean   is_toplevel)
9124 {
9125   GtkWidget *widget;
9126
9127   widget = GTK_WIDGET (window);
9128
9129   if (gtk_widget_is_toplevel (widget))
9130     g_assert (g_slist_find (toplevel_list, window) != NULL);
9131   else
9132     g_assert (g_slist_find (toplevel_list, window) == NULL);
9133
9134   if (is_toplevel == gtk_widget_is_toplevel (widget))
9135     return;
9136
9137   if (is_toplevel)
9138     {
9139       _gtk_widget_set_is_toplevel (widget, TRUE);
9140       toplevel_list = g_slist_prepend (toplevel_list, window);
9141     }
9142   else
9143     {
9144       _gtk_widget_set_is_toplevel (widget, FALSE);
9145       toplevel_list = g_slist_remove (toplevel_list, window);
9146     }
9147 }
9148
9149 /**
9150  * _gtk_window_set_has_toplevel_focus:
9151  * @window: a #GtkWindow
9152  * @has_toplevel_focus: %TRUE if the in
9153  * 
9154  * Internal function that sets whether the keyboard focus for the
9155  * toplevel window (taking into account inter-process embedding.)
9156  **/
9157 void
9158 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
9159                                    gboolean   has_toplevel_focus)
9160 {
9161   GtkWindowPrivate *priv;
9162
9163   g_return_if_fail (GTK_IS_WINDOW (window));
9164
9165   priv = window->priv;
9166
9167   has_toplevel_focus = has_toplevel_focus != FALSE;
9168
9169   if (has_toplevel_focus != priv->has_toplevel_focus)
9170     {
9171       priv->has_toplevel_focus = has_toplevel_focus;
9172       window_update_has_focus (window);
9173
9174       g_object_notify (G_OBJECT (window), "has-toplevel-focus");
9175     }
9176 }
9177
9178 /**
9179  * gtk_window_set_auto_startup_notification:
9180  * @setting: %TRUE to automatically do startup notification
9181  *
9182  * By default, after showing the first #GtkWindow, GTK+ calls 
9183  * gdk_notify_startup_complete().  Call this function to disable 
9184  * the automatic startup notification. You might do this if your 
9185  * first window is a splash screen, and you want to delay notification 
9186  * until after your real main window has been shown, for example.
9187  *
9188  * In that example, you would disable startup notification
9189  * temporarily, show your splash screen, then re-enable it so that
9190  * showing the main window would automatically result in notification.
9191  * 
9192  * Since: 2.2
9193  **/
9194 void
9195 gtk_window_set_auto_startup_notification (gboolean setting)
9196 {
9197   disable_startup_notification = !setting;
9198 }
9199
9200 /**
9201  * gtk_window_get_window_type:
9202  * @window: a #GtkWindow
9203  *
9204  * Gets the type of the window. See #GtkWindowType.
9205  *
9206  * Return value: the type of the window
9207  *
9208  * Since: 2.20
9209  **/
9210 GtkWindowType
9211 gtk_window_get_window_type (GtkWindow *window)
9212 {
9213   g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
9214
9215   return window->priv->type;
9216 }
9217
9218 /**
9219  * gtk_window_get_mnemonics_visible:
9220  * @window: a #GtkWindow
9221  *
9222  * Gets the value of the #GtkWindow:mnemonics-visible property.
9223  *
9224  * Returns: %TRUE if mnemonics are supposed to be visible
9225  * in this window.
9226  *
9227  * Since: 2.20
9228  */
9229 gboolean
9230 gtk_window_get_mnemonics_visible (GtkWindow *window)
9231 {
9232   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
9233
9234   return window->priv->mnemonics_visible;
9235 }
9236
9237 /**
9238  * gtk_window_set_mnemonics_visible:
9239  * @window: a #GtkWindow
9240  * @setting: the new value
9241  *
9242  * Sets the #GtkWindow:mnemonics-visible property.
9243  *
9244  * Since: 2.20
9245  */
9246 void
9247 gtk_window_set_mnemonics_visible (GtkWindow *window,
9248                                   gboolean   setting)
9249 {
9250   GtkWindowPrivate *priv;
9251
9252   g_return_if_fail (GTK_IS_WINDOW (window));
9253
9254   priv = window->priv;
9255
9256   setting = setting != FALSE;
9257
9258   if (priv->mnemonics_visible != setting)
9259     {
9260       priv->mnemonics_visible = setting;
9261       g_object_notify (G_OBJECT (window), "mnemonics-visible");
9262     }
9263
9264   priv->mnemonics_visible_set = TRUE;
9265 }
9266
9267 void
9268 _gtk_window_get_wmclass (GtkWindow  *window,
9269                          gchar     **wmclass_name,
9270                          gchar     **wmclass_class)
9271 {
9272   GtkWindowPrivate *priv = window->priv;
9273
9274   *wmclass_name = priv->wmclass_name;
9275   *wmclass_class = priv->wmclass_class;
9276 }