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