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