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