]> Pileus Git - ~andy/gtk/blob - gtk/gtkwindow.c
1695e1804139c55add4661d467869f3176a7d63c
[~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_UNSET_FLAGS (window, GTK_NO_WINDOW);
904   GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
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_REALIZED (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_REALIZED (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_REALIZED (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_REALIZED (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_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
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_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
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_REALIZED (window))
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_REALIZED (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_REALIZED (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
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  * On Windows, this function puts the child window on top of the parent, 
2282  * much as the window manager would have done on X.
2283  * 
2284  **/
2285 void       
2286 gtk_window_set_transient_for  (GtkWindow *window, 
2287                                GtkWindow *parent)
2288 {
2289   GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
2290   
2291   g_return_if_fail (GTK_IS_WINDOW (window));
2292   g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
2293   g_return_if_fail (window != parent);
2294
2295   if (window->transient_parent)
2296     {
2297       if (GTK_WIDGET_REALIZED (window) && 
2298           GTK_WIDGET_REALIZED (window->transient_parent) && 
2299           (!parent || !GTK_WIDGET_REALIZED (parent)))
2300         gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
2301                                                 GTK_WIDGET (window));
2302
2303       gtk_window_unset_transient_for (window);
2304     }
2305
2306   window->transient_parent = parent;
2307   
2308   if (parent)
2309     {
2310       g_signal_connect (parent, "destroy",
2311                         G_CALLBACK (gtk_widget_destroyed),
2312                         &window->transient_parent);
2313       g_signal_connect (parent, "realize",
2314                         G_CALLBACK (gtk_window_transient_parent_realized),
2315                         window);
2316       g_signal_connect (parent, "unrealize",
2317                         G_CALLBACK (gtk_window_transient_parent_unrealized),
2318                         window);
2319       g_signal_connect (parent, "notify::screen",
2320                         G_CALLBACK (gtk_window_transient_parent_screen_changed),
2321                         window);
2322       
2323       gtk_window_set_screen (window, parent->screen);
2324
2325       if (window->destroy_with_parent)
2326         connect_parent_destroyed (window);
2327       
2328       if (GTK_WIDGET_REALIZED (window) &&
2329           GTK_WIDGET_REALIZED (parent))
2330         gtk_window_transient_parent_realized (GTK_WIDGET (parent),
2331                                               GTK_WIDGET (window));
2332
2333       if (parent->group)
2334         {
2335           gtk_window_group_add_window (parent->group, window);
2336           priv->transient_parent_group = TRUE;
2337         }
2338     }
2339 }
2340
2341 /**
2342  * gtk_window_get_transient_for:
2343  * @window: a #GtkWindow
2344  *
2345  * Fetches the transient parent for this window. See
2346  * gtk_window_set_transient_for().
2347  *
2348  * Return value: (transfer none): the transient parent for this window, or %NULL
2349  *    if no transient parent has been set.
2350  **/
2351 GtkWindow *
2352 gtk_window_get_transient_for (GtkWindow *window)
2353 {
2354   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
2355
2356   return window->transient_parent;
2357 }
2358
2359 /**
2360  * gtk_window_set_opacity:
2361  * @window: a #GtkWindow
2362  * @opacity: desired opacity, between 0 and 1
2363  *
2364  * Request the windowing system to make @window partially transparent,
2365  * with opacity 0 being fully transparent and 1 fully opaque. (Values
2366  * of the opacity parameter are clamped to the [0,1] range.) On X11
2367  * this has any effect only on X screens with a compositing manager
2368  * running. See gtk_widget_is_composited(). On Windows it should work
2369  * always.
2370  * 
2371  * Note that setting a window's opacity after the window has been
2372  * shown causes it to flicker once on Windows.
2373  *
2374  * Since: 2.12
2375  **/
2376 void       
2377 gtk_window_set_opacity  (GtkWindow *window, 
2378                          gdouble    opacity)
2379 {
2380   GtkWindowPrivate *priv;
2381   
2382   g_return_if_fail (GTK_IS_WINDOW (window));
2383
2384   priv = GTK_WINDOW_GET_PRIVATE (window); 
2385
2386   if (opacity < 0.0)
2387     opacity = 0.0;
2388   else if (opacity > 1.0)
2389     opacity = 1.0;
2390
2391   priv->opacity_set = TRUE;
2392   priv->opacity = opacity;
2393
2394   if (GTK_WIDGET_REALIZED (window))
2395     gdk_window_set_opacity (GTK_WIDGET (window)->window, priv->opacity);
2396 }
2397
2398 /**
2399  * gtk_window_get_opacity:
2400  * @window: a #GtkWindow
2401  *
2402  * Fetches the requested opacity for this window. See
2403  * gtk_window_set_opacity().
2404  *
2405  * Return value: the requested opacity for this window.
2406  *
2407  * Since: 2.12
2408  **/
2409 gdouble
2410 gtk_window_get_opacity (GtkWindow *window)
2411 {
2412   GtkWindowPrivate *priv;
2413   
2414   g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0);
2415
2416   priv = GTK_WINDOW_GET_PRIVATE (window); 
2417
2418   return priv->opacity;
2419 }
2420
2421 /**
2422  * gtk_window_set_type_hint:
2423  * @window: a #GtkWindow
2424  * @hint: the window type
2425  *
2426  * By setting the type hint for the window, you allow the window
2427  * manager to decorate and handle the window in a way which is
2428  * suitable to the function of the window in your application.
2429  *
2430  * This function should be called before the window becomes visible.
2431  *
2432  * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
2433  * will sometimes call gtk_window_set_type_hint() on your behalf.
2434  * 
2435  **/
2436 void
2437 gtk_window_set_type_hint (GtkWindow           *window, 
2438                           GdkWindowTypeHint    hint)
2439 {
2440   GtkWindowPrivate *priv;
2441
2442   g_return_if_fail (GTK_IS_WINDOW (window));
2443   g_return_if_fail (!gtk_widget_get_mapped (GTK_WIDGET (window)));
2444
2445   priv = GTK_WINDOW_GET_PRIVATE (window);
2446
2447   if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU)
2448     window->type_hint = hint;
2449   else
2450     window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
2451
2452   priv->reset_type_hint = TRUE;
2453   priv->type_hint = hint;
2454 }
2455
2456 /**
2457  * gtk_window_get_type_hint:
2458  * @window: a #GtkWindow
2459  *
2460  * Gets the type hint for this window. See gtk_window_set_type_hint().
2461  *
2462  * Return value: the type hint for @window.
2463  **/
2464 GdkWindowTypeHint
2465 gtk_window_get_type_hint (GtkWindow *window)
2466 {
2467   GtkWindowPrivate *priv;
2468   
2469   g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2470
2471   priv = GTK_WINDOW_GET_PRIVATE (window);
2472   
2473   return priv->type_hint;
2474 }
2475
2476 /**
2477  * gtk_window_set_skip_taskbar_hint:
2478  * @window: a #GtkWindow 
2479  * @setting: %TRUE to keep this window from appearing in the task bar
2480  * 
2481  * Windows may set a hint asking the desktop environment not to display
2482  * the window in the task bar. This function sets this hint.
2483  * 
2484  * Since: 2.2
2485  **/
2486 void
2487 gtk_window_set_skip_taskbar_hint (GtkWindow *window,
2488                                   gboolean   setting)
2489 {
2490   GtkWindowPrivate *priv;
2491
2492   g_return_if_fail (GTK_IS_WINDOW (window));
2493   
2494   priv = GTK_WINDOW_GET_PRIVATE (window);
2495
2496   setting = setting != FALSE;
2497
2498   if (priv->skips_taskbar != setting)
2499     {
2500       priv->skips_taskbar = setting;
2501       if (GTK_WIDGET_REALIZED (window))
2502         gdk_window_set_skip_taskbar_hint (GTK_WIDGET (window)->window,
2503                                           priv->skips_taskbar);
2504       g_object_notify (G_OBJECT (window), "skip-taskbar-hint");
2505     }
2506 }
2507
2508 /**
2509  * gtk_window_get_skip_taskbar_hint:
2510  * @window: a #GtkWindow
2511  * 
2512  * Gets the value set by gtk_window_set_skip_taskbar_hint()
2513  * 
2514  * Return value: %TRUE if window shouldn't be in taskbar
2515  * 
2516  * Since: 2.2
2517  **/
2518 gboolean
2519 gtk_window_get_skip_taskbar_hint (GtkWindow *window)
2520 {
2521   GtkWindowPrivate *priv;
2522
2523   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2524   
2525   priv = GTK_WINDOW_GET_PRIVATE (window);
2526
2527   return priv->skips_taskbar;
2528 }
2529
2530 /**
2531  * gtk_window_set_skip_pager_hint:
2532  * @window: a #GtkWindow 
2533  * @setting: %TRUE to keep this window from appearing in the pager
2534  * 
2535  * Windows may set a hint asking the desktop environment not to display
2536  * the window in the pager. This function sets this hint.
2537  * (A "pager" is any desktop navigation tool such as a workspace
2538  * switcher that displays a thumbnail representation of the windows
2539  * on the screen.)
2540  * 
2541  * Since: 2.2
2542  **/
2543 void
2544 gtk_window_set_skip_pager_hint (GtkWindow *window,
2545                                 gboolean   setting)
2546 {
2547   GtkWindowPrivate *priv;
2548
2549   g_return_if_fail (GTK_IS_WINDOW (window));
2550   
2551   priv = GTK_WINDOW_GET_PRIVATE (window);
2552
2553   setting = setting != FALSE;
2554
2555   if (priv->skips_pager != setting)
2556     {
2557       priv->skips_pager = setting;
2558       if (GTK_WIDGET_REALIZED (window))
2559         gdk_window_set_skip_pager_hint (GTK_WIDGET (window)->window,
2560                                         priv->skips_pager);
2561       g_object_notify (G_OBJECT (window), "skip-pager-hint");
2562     }
2563 }
2564
2565 /**
2566  * gtk_window_get_skip_pager_hint:
2567  * @window: a #GtkWindow
2568  * 
2569  * Gets the value set by gtk_window_set_skip_pager_hint().
2570  * 
2571  * Return value: %TRUE if window shouldn't be in pager
2572  * 
2573  * Since: 2.2
2574  **/
2575 gboolean
2576 gtk_window_get_skip_pager_hint (GtkWindow *window)
2577 {
2578   GtkWindowPrivate *priv;
2579
2580   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2581   
2582   priv = GTK_WINDOW_GET_PRIVATE (window);
2583
2584   return priv->skips_pager;
2585 }
2586
2587 /**
2588  * gtk_window_set_urgency_hint:
2589  * @window: a #GtkWindow 
2590  * @setting: %TRUE to mark this window as urgent
2591  * 
2592  * Windows may set a hint asking the desktop environment to draw
2593  * the users attention to the window. This function sets this hint.
2594  * 
2595  * Since: 2.8
2596  **/
2597 void
2598 gtk_window_set_urgency_hint (GtkWindow *window,
2599                              gboolean   setting)
2600 {
2601   GtkWindowPrivate *priv;
2602
2603   g_return_if_fail (GTK_IS_WINDOW (window));
2604   
2605   priv = GTK_WINDOW_GET_PRIVATE (window);
2606
2607   setting = setting != FALSE;
2608
2609   if (priv->urgent != setting)
2610     {
2611       priv->urgent = setting;
2612       if (GTK_WIDGET_REALIZED (window))
2613         gdk_window_set_urgency_hint (GTK_WIDGET (window)->window,
2614                                      priv->urgent);
2615       g_object_notify (G_OBJECT (window), "urgency-hint");
2616     }
2617 }
2618
2619 /**
2620  * gtk_window_get_urgency_hint:
2621  * @window: a #GtkWindow
2622  * 
2623  * Gets the value set by gtk_window_set_urgency_hint()
2624  * 
2625  * Return value: %TRUE if window is urgent
2626  * 
2627  * Since: 2.8
2628  **/
2629 gboolean
2630 gtk_window_get_urgency_hint (GtkWindow *window)
2631 {
2632   GtkWindowPrivate *priv;
2633
2634   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2635   
2636   priv = GTK_WINDOW_GET_PRIVATE (window);
2637
2638   return priv->urgent;
2639 }
2640
2641 /**
2642  * gtk_window_set_accept_focus:
2643  * @window: a #GtkWindow 
2644  * @setting: %TRUE to let this window receive input focus
2645  * 
2646  * Windows may set a hint asking the desktop environment not to receive
2647  * the input focus. This function sets this hint.
2648  * 
2649  * Since: 2.4
2650  **/
2651 void
2652 gtk_window_set_accept_focus (GtkWindow *window,
2653                              gboolean   setting)
2654 {
2655   GtkWindowPrivate *priv;
2656
2657   g_return_if_fail (GTK_IS_WINDOW (window));
2658   
2659   priv = GTK_WINDOW_GET_PRIVATE (window);
2660
2661   setting = setting != FALSE;
2662
2663   if (priv->accept_focus != setting)
2664     {
2665       priv->accept_focus = setting;
2666       if (GTK_WIDGET_REALIZED (window))
2667         gdk_window_set_accept_focus (GTK_WIDGET (window)->window,
2668                                      priv->accept_focus);
2669       g_object_notify (G_OBJECT (window), "accept-focus");
2670     }
2671 }
2672
2673 /**
2674  * gtk_window_get_accept_focus:
2675  * @window: a #GtkWindow
2676  * 
2677  * Gets the value set by gtk_window_set_accept_focus().
2678  * 
2679  * Return value: %TRUE if window should receive the input focus
2680  * 
2681  * Since: 2.4
2682  **/
2683 gboolean
2684 gtk_window_get_accept_focus (GtkWindow *window)
2685 {
2686   GtkWindowPrivate *priv;
2687
2688   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2689   
2690   priv = GTK_WINDOW_GET_PRIVATE (window);
2691
2692   return priv->accept_focus;
2693 }
2694
2695 /**
2696  * gtk_window_set_focus_on_map:
2697  * @window: a #GtkWindow 
2698  * @setting: %TRUE to let this window receive input focus on map
2699  * 
2700  * Windows may set a hint asking the desktop environment not to receive
2701  * the input focus when the window is mapped.  This function sets this
2702  * hint.
2703  * 
2704  * Since: 2.6
2705  **/
2706 void
2707 gtk_window_set_focus_on_map (GtkWindow *window,
2708                              gboolean   setting)
2709 {
2710   GtkWindowPrivate *priv;
2711
2712   g_return_if_fail (GTK_IS_WINDOW (window));
2713   
2714   priv = GTK_WINDOW_GET_PRIVATE (window);
2715
2716   setting = setting != FALSE;
2717
2718   if (priv->focus_on_map != setting)
2719     {
2720       priv->focus_on_map = setting;
2721       if (GTK_WIDGET_REALIZED (window))
2722         gdk_window_set_focus_on_map (GTK_WIDGET (window)->window,
2723                                      priv->focus_on_map);
2724       g_object_notify (G_OBJECT (window), "focus-on-map");
2725     }
2726 }
2727
2728 /**
2729  * gtk_window_get_focus_on_map:
2730  * @window: a #GtkWindow
2731  * 
2732  * Gets the value set by gtk_window_set_focus_on_map().
2733  * 
2734  * Return value: %TRUE if window should receive the input focus when
2735  * mapped.
2736  * 
2737  * Since: 2.6
2738  **/
2739 gboolean
2740 gtk_window_get_focus_on_map (GtkWindow *window)
2741 {
2742   GtkWindowPrivate *priv;
2743
2744   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2745   
2746   priv = GTK_WINDOW_GET_PRIVATE (window);
2747
2748   return priv->focus_on_map;
2749 }
2750
2751 /**
2752  * gtk_window_set_destroy_with_parent:
2753  * @window: a #GtkWindow
2754  * @setting: whether to destroy @window with its transient parent
2755  * 
2756  * If @setting is %TRUE, then destroying the transient parent of @window
2757  * will also destroy @window itself. This is useful for dialogs that
2758  * shouldn't persist beyond the lifetime of the main window they're
2759  * associated with, for example.
2760  **/
2761 void
2762 gtk_window_set_destroy_with_parent  (GtkWindow *window,
2763                                      gboolean   setting)
2764 {
2765   g_return_if_fail (GTK_IS_WINDOW (window));
2766
2767   if (window->destroy_with_parent == (setting != FALSE))
2768     return;
2769
2770   if (window->destroy_with_parent)
2771     {
2772       disconnect_parent_destroyed (window);
2773     }
2774   else
2775     {
2776       connect_parent_destroyed (window);
2777     }
2778   
2779   window->destroy_with_parent = setting;
2780
2781   g_object_notify (G_OBJECT (window), "destroy-with-parent");
2782 }
2783
2784 /**
2785  * gtk_window_get_destroy_with_parent:
2786  * @window: a #GtkWindow
2787  * 
2788  * Returns whether the window will be destroyed with its transient parent. See
2789  * gtk_window_set_destroy_with_parent ().
2790  *
2791  * Return value: %TRUE if the window will be destroyed with its transient parent.
2792  **/
2793 gboolean
2794 gtk_window_get_destroy_with_parent (GtkWindow *window)
2795 {
2796   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
2797
2798   return window->destroy_with_parent;
2799 }
2800
2801 static GtkWindowGeometryInfo*
2802 gtk_window_get_geometry_info (GtkWindow *window,
2803                               gboolean   create)
2804 {
2805   GtkWindowGeometryInfo *info;
2806
2807   info = window->geometry_info;
2808   if (!info && create)
2809     {
2810       info = g_new0 (GtkWindowGeometryInfo, 1);
2811
2812       info->default_width = -1;
2813       info->default_height = -1;
2814       info->resize_width = -1;
2815       info->resize_height = -1;
2816       info->initial_x = 0;
2817       info->initial_y = 0;
2818       info->initial_pos_set = FALSE;
2819       info->default_is_geometry = FALSE;
2820       info->position_constraints_changed = FALSE;
2821       info->last.configure_request.x = 0;
2822       info->last.configure_request.y = 0;
2823       info->last.configure_request.width = -1;
2824       info->last.configure_request.height = -1;
2825       info->widget = NULL;
2826       info->mask = 0;
2827       window->geometry_info = info;
2828     }
2829
2830   return info;
2831 }
2832
2833 /**
2834  * gtk_window_set_geometry_hints:
2835  * @window: a #GtkWindow
2836  * @geometry_widget: widget the geometry hints will be applied to
2837  * @geometry: struct containing geometry information
2838  * @geom_mask: mask indicating which struct fields should be paid attention to
2839  *
2840  * This function sets up hints about how a window can be resized by
2841  * the user.  You can set a minimum and maximum size; allowed resize
2842  * increments (e.g. for xterm, you can only resize by the size of a
2843  * character); aspect ratios; and more. See the #GdkGeometry struct.
2844  * 
2845  **/
2846 void       
2847 gtk_window_set_geometry_hints (GtkWindow       *window,
2848                                GtkWidget       *geometry_widget,
2849                                GdkGeometry     *geometry,
2850                                GdkWindowHints   geom_mask)
2851 {
2852   GtkWindowGeometryInfo *info;
2853
2854   g_return_if_fail (GTK_IS_WINDOW (window));
2855   g_return_if_fail (geometry_widget == NULL || GTK_IS_WIDGET (geometry_widget));
2856
2857   info = gtk_window_get_geometry_info (window, TRUE);
2858   
2859   if (info->widget)
2860     g_signal_handlers_disconnect_by_func (info->widget,
2861                                           gtk_widget_destroyed,
2862                                           &info->widget);
2863   
2864   info->widget = geometry_widget;
2865   if (info->widget)
2866     g_signal_connect (geometry_widget, "destroy",
2867                       G_CALLBACK (gtk_widget_destroyed),
2868                       &info->widget);
2869
2870   if (geometry)
2871     info->geometry = *geometry;
2872
2873   /* We store gravity in window->gravity not in the hints. */
2874   info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY);
2875
2876   if (geom_mask & GDK_HINT_WIN_GRAVITY)
2877     {
2878       gtk_window_set_gravity (window, geometry->win_gravity);
2879     }
2880   
2881   gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
2882 }
2883
2884 /**
2885  * gtk_window_set_decorated:
2886  * @window: a #GtkWindow
2887  * @setting: %TRUE to decorate the window
2888  *
2889  * By default, windows are decorated with a title bar, resize
2890  * controls, etc.  Some <link linkend="gtk-X11-arch">window
2891  * managers</link> allow GTK+ to disable these decorations, creating a
2892  * borderless window. If you set the decorated property to %FALSE
2893  * using this function, GTK+ will do its best to convince the window
2894  * manager not to decorate the window. Depending on the system, this
2895  * function may not have any effect when called on a window that is
2896  * already visible, so you should call it before calling gtk_window_show().
2897  *
2898  * On Windows, this function always works, since there's no window manager
2899  * policy involved.
2900  * 
2901  **/
2902 void
2903 gtk_window_set_decorated (GtkWindow *window,
2904                           gboolean   setting)
2905 {
2906   g_return_if_fail (GTK_IS_WINDOW (window));
2907
2908   setting = setting != FALSE;
2909
2910   if (setting == window->decorated)
2911     return;
2912
2913   window->decorated = setting;
2914   
2915   if (GTK_WIDGET (window)->window)
2916     {
2917       if (window->decorated)
2918         gdk_window_set_decorations (GTK_WIDGET (window)->window,
2919                                     GDK_DECOR_ALL);
2920       else
2921         gdk_window_set_decorations (GTK_WIDGET (window)->window,
2922                                     0);
2923     }
2924
2925   g_object_notify (G_OBJECT (window), "decorated");
2926 }
2927
2928 /**
2929  * gtk_window_get_decorated:
2930  * @window: a #GtkWindow
2931  *
2932  * Returns whether the window has been set to have decorations
2933  * such as a title bar via gtk_window_set_decorated().
2934  *
2935  * Return value: %TRUE if the window has been set to have decorations
2936  **/
2937 gboolean
2938 gtk_window_get_decorated (GtkWindow *window)
2939 {
2940   g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
2941
2942   return window->decorated;
2943 }
2944
2945 /**
2946  * gtk_window_set_deletable:
2947  * @window: a #GtkWindow
2948  * @setting: %TRUE to decorate the window as deletable
2949  *
2950  * By default, windows have a close button in the window frame. Some 
2951  * <link linkend="gtk-X11-arch">window managers</link> allow GTK+ to 
2952  * disable this button. If you set the deletable property to %FALSE
2953  * using this function, GTK+ will do its best to convince the window
2954  * manager not to show a close button. Depending on the system, this
2955  * function may not have any effect when called on a window that is
2956  * already visible, so you should call it before calling gtk_window_show().
2957  *
2958  * On Windows, this function always works, since there's no window manager
2959  * policy involved.
2960  *
2961  * Since: 2.10
2962  */
2963 void
2964 gtk_window_set_deletable (GtkWindow *window,
2965                           gboolean   setting)
2966 {
2967   GtkWindowPrivate *priv;
2968
2969   g_return_if_fail (GTK_IS_WINDOW (window));
2970
2971   priv = GTK_WINDOW_GET_PRIVATE (window);
2972
2973   setting = setting != FALSE;
2974
2975   if (setting == priv->deletable)
2976     return;
2977
2978   priv->deletable = setting;
2979   
2980   if (GTK_WIDGET (window)->window)
2981     {
2982       if (priv->deletable)
2983         gdk_window_set_functions (GTK_WIDGET (window)->window,
2984                                   GDK_FUNC_ALL);
2985       else
2986         gdk_window_set_functions (GTK_WIDGET (window)->window,
2987                                   GDK_FUNC_ALL | GDK_FUNC_CLOSE);
2988     }
2989
2990   g_object_notify (G_OBJECT (window), "deletable");  
2991 }
2992
2993 /**
2994  * gtk_window_get_deletable:
2995  * @window: a #GtkWindow
2996  *
2997  * Returns whether the window has been set to have a close button
2998  * via gtk_window_set_deletable().
2999  *
3000  * Return value: %TRUE if the window has been set to have a close button
3001  *
3002  * Since: 2.10
3003  **/
3004 gboolean
3005 gtk_window_get_deletable (GtkWindow *window)
3006 {
3007   GtkWindowPrivate *priv;
3008
3009   g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE);
3010
3011   priv = GTK_WINDOW_GET_PRIVATE (window);
3012
3013   return priv->deletable;
3014 }
3015
3016 static GtkWindowIconInfo*
3017 get_icon_info (GtkWindow *window)
3018 {
3019   return g_object_get_qdata (G_OBJECT (window), quark_gtk_window_icon_info);
3020 }
3021      
3022 static void
3023 free_icon_info (GtkWindowIconInfo *info)
3024 {
3025   g_free (info->icon_name);
3026   g_slice_free (GtkWindowIconInfo, info);
3027 }
3028
3029
3030 static GtkWindowIconInfo*
3031 ensure_icon_info (GtkWindow *window)
3032 {
3033   GtkWindowIconInfo *info;
3034
3035   info = get_icon_info (window);
3036   
3037   if (info == NULL)
3038     {
3039       info = g_slice_new0 (GtkWindowIconInfo);
3040       g_object_set_qdata_full (G_OBJECT (window),
3041                               quark_gtk_window_icon_info,
3042                               info,
3043                               (GDestroyNotify)free_icon_info);
3044     }
3045
3046   return info;
3047 }
3048
3049 typedef struct {
3050   guint serial;
3051   GdkPixmap *pixmap;
3052   GdkPixmap *mask;
3053 } ScreenIconInfo;
3054
3055 static ScreenIconInfo *
3056 get_screen_icon_info (GdkScreen *screen)
3057 {
3058   ScreenIconInfo *info = g_object_get_qdata (G_OBJECT (screen), 
3059                                              quark_gtk_window_default_icon_pixmap);
3060   if (!info)
3061     {
3062       info = g_slice_new0 (ScreenIconInfo);
3063       g_object_set_qdata (G_OBJECT (screen), 
3064                           quark_gtk_window_default_icon_pixmap, info);
3065     }
3066
3067   if (info->serial != default_icon_serial)
3068     {
3069       if (info->pixmap)
3070         {
3071           g_object_remove_weak_pointer (G_OBJECT (info->pixmap), (gpointer*)&info->pixmap);
3072           info->pixmap = NULL;
3073         }
3074           
3075       if (info->mask)
3076         {
3077           g_object_remove_weak_pointer (G_OBJECT (info->mask), (gpointer*)&info->mask);
3078           info->mask = NULL;
3079         }
3080
3081       info->serial = default_icon_serial;
3082     }
3083   
3084   return info;
3085 }
3086
3087 static void
3088 get_pixmap_and_mask (GdkWindow          *window,
3089                      GtkWindowIconInfo  *parent_info,
3090                      gboolean            is_default_list,
3091                      GList              *icon_list,
3092                      GdkPixmap         **pmap_return,
3093                      GdkBitmap         **mask_return)
3094 {
3095   GdkScreen *screen = gdk_drawable_get_screen (window);
3096   ScreenIconInfo *default_icon_info = get_screen_icon_info (screen);
3097   GdkPixbuf *best_icon;
3098   GList *tmp_list;
3099   int best_size;
3100   
3101   *pmap_return = NULL;
3102   *mask_return = NULL;
3103   
3104   if (is_default_list &&
3105       default_icon_info->pixmap != NULL)
3106     {
3107       /* Use shared icon pixmap for all windows on this screen.
3108        */
3109       if (default_icon_info->pixmap)
3110         g_object_ref (default_icon_info->pixmap);
3111       if (default_icon_info->mask)
3112         g_object_ref (default_icon_info->mask);
3113
3114       *pmap_return = default_icon_info->pixmap;
3115       *mask_return = default_icon_info->mask;
3116     }
3117   else if (parent_info && parent_info->icon_pixmap)
3118     {
3119       if (parent_info->icon_pixmap)
3120         g_object_ref (parent_info->icon_pixmap);
3121       if (parent_info->icon_mask)
3122         g_object_ref (parent_info->icon_mask);
3123       
3124       *pmap_return = parent_info->icon_pixmap;
3125       *mask_return = parent_info->icon_mask;
3126     }
3127   else
3128     {
3129 #define IDEAL_SIZE 48
3130   
3131       best_size = G_MAXINT;
3132       best_icon = NULL;
3133       tmp_list = icon_list;
3134       while (tmp_list != NULL)
3135         {
3136           GdkPixbuf *pixbuf = tmp_list->data;
3137           int this;
3138       
3139           /* average width and height - if someone passes in a rectangular
3140            * icon they deserve what they get.
3141            */
3142           this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
3143           this /= 2;
3144       
3145           if (best_icon == NULL)
3146             {
3147               best_icon = pixbuf;
3148               best_size = this;
3149             }
3150           else
3151             {
3152               /* icon is better if it's 32 pixels or larger, and closer to
3153                * the ideal size than the current best.
3154                */
3155               if (this >= 32 &&
3156                   (ABS (best_size - IDEAL_SIZE) <
3157                    ABS (this - IDEAL_SIZE)))
3158                 {
3159                   best_icon = pixbuf;
3160                   best_size = this;
3161                 }
3162             }
3163
3164           tmp_list = tmp_list->next;
3165         }
3166
3167       if (best_icon)
3168         gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon,
3169                                                         gdk_screen_get_system_colormap (screen),
3170                                                         pmap_return,
3171                                                         mask_return,
3172                                                         128);
3173
3174       /* Save pmap/mask for others to use if appropriate */
3175       if (parent_info)
3176         {
3177           parent_info->icon_pixmap = *pmap_return;
3178           parent_info->icon_mask = *mask_return;
3179
3180           if (parent_info->icon_pixmap)
3181             g_object_ref (parent_info->icon_pixmap);
3182           if (parent_info->icon_mask)
3183             g_object_ref (parent_info->icon_mask);
3184         }
3185       else if (is_default_list)
3186         {
3187           default_icon_info->pixmap = *pmap_return;
3188           default_icon_info->mask = *mask_return;
3189
3190           if (default_icon_info->pixmap)
3191             g_object_add_weak_pointer (G_OBJECT (default_icon_info->pixmap),
3192                                        (gpointer*)&default_icon_info->pixmap);
3193           if (default_icon_info->mask) 
3194             g_object_add_weak_pointer (G_OBJECT (default_icon_info->mask),
3195                                        (gpointer*)&default_icon_info->mask);
3196         }
3197     }
3198 }
3199
3200 static GList *
3201 icon_list_from_theme (GtkWidget    *widget,
3202                       const gchar  *name)
3203 {
3204   GList *list;
3205
3206   GtkIconTheme *icon_theme;
3207   GdkPixbuf *icon;
3208   gint *sizes;
3209   gint i;
3210
3211   icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
3212
3213   sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name);
3214
3215   list = NULL;
3216   for (i = 0; sizes[i]; i++)
3217     {      
3218       /* FIXME
3219        * We need an EWMH extension to handle scalable icons 
3220        * by passing their name to the WM. For now just use a 
3221        * fixed size of 48.
3222        */ 
3223       if (sizes[i] == -1)
3224         icon = gtk_icon_theme_load_icon (icon_theme, name,
3225                                          48, 0, NULL);
3226       else
3227         icon = gtk_icon_theme_load_icon (icon_theme, name,
3228                                          sizes[i], 0, NULL);
3229       if (icon)
3230         list = g_list_append (list, icon);
3231     }
3232
3233   g_free (sizes);
3234
3235   return list;
3236 }
3237
3238
3239 static void
3240 gtk_window_realize_icon (GtkWindow *window)
3241 {
3242   GtkWidget *widget;
3243   GtkWindowIconInfo *info;
3244   GList *icon_list;
3245
3246   widget = GTK_WIDGET (window);
3247
3248   g_return_if_fail (widget->window != NULL);
3249
3250   /* no point setting an icon on override-redirect */
3251   if (window->type == GTK_WINDOW_POPUP)
3252     return;
3253
3254   icon_list = NULL;
3255   
3256   info = ensure_icon_info (window);
3257
3258   if (info->realized)
3259     return;
3260
3261   g_return_if_fail (info->icon_pixmap == NULL);
3262   g_return_if_fail (info->icon_mask == NULL);
3263   
3264   info->using_default_icon = FALSE;
3265   info->using_parent_icon = FALSE;
3266   info->using_themed_icon = FALSE;
3267   
3268   icon_list = info->icon_list;
3269
3270   /* Look up themed icon */
3271   if (icon_list == NULL && info->icon_name) 
3272     {
3273       icon_list = icon_list_from_theme (widget, info->icon_name);
3274       if (icon_list)
3275         info->using_themed_icon = TRUE;
3276     }
3277
3278   /* Inherit from transient parent */
3279   if (icon_list == NULL && window->transient_parent)
3280     {
3281       icon_list = ensure_icon_info (window->transient_parent)->icon_list;
3282       if (icon_list)
3283         info->using_parent_icon = TRUE;
3284     }      
3285
3286   /* Inherit from default */
3287   if (icon_list == NULL)
3288     {
3289       icon_list = default_icon_list;
3290       if (icon_list)
3291         info->using_default_icon = TRUE;
3292     }
3293
3294   /* Look up themed icon */
3295   if (icon_list == NULL && default_icon_name) 
3296     {
3297       icon_list = icon_list_from_theme (widget, default_icon_name);
3298       info->using_default_icon = TRUE;
3299       info->using_themed_icon = TRUE;  
3300     }
3301   
3302   gdk_window_set_icon_list (widget->window, icon_list);
3303
3304   get_pixmap_and_mask (widget->window,
3305                        info->using_parent_icon ? ensure_icon_info (window->transient_parent) : NULL,
3306                        info->using_default_icon,
3307                        icon_list,
3308                        &info->icon_pixmap,
3309                        &info->icon_mask);
3310   
3311   /* This is a slight ICCCM violation since it's a color pixmap not
3312    * a bitmap, but everyone does it.
3313    */
3314   gdk_window_set_icon (widget->window,
3315                        NULL,
3316                        info->icon_pixmap,
3317                        info->icon_mask);
3318
3319   info->realized = TRUE;
3320   
3321   if (info->using_themed_icon) 
3322     {
3323       GtkIconTheme *icon_theme;
3324
3325       g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
3326       g_list_free (icon_list);
3327  
3328       icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3329       g_signal_connect (icon_theme, "changed",
3330                         G_CALLBACK (update_themed_icon), window);
3331     }
3332 }
3333
3334 static void
3335 gtk_window_unrealize_icon (GtkWindow *window)
3336 {
3337   GtkWindowIconInfo *info;
3338
3339   info = get_icon_info (window);
3340
3341   if (info == NULL)
3342     return;
3343   
3344   if (info->icon_pixmap)
3345     g_object_unref (info->icon_pixmap);
3346
3347   if (info->icon_mask)
3348     g_object_unref (info->icon_mask);
3349
3350   info->icon_pixmap = NULL;
3351   info->icon_mask = NULL;
3352
3353   if (info->using_themed_icon)
3354     {
3355       GtkIconTheme *icon_theme;
3356
3357       icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
3358
3359       g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window);
3360     }
3361     
3362   /* We don't clear the properties on the window, just figure the
3363    * window is going away.
3364    */
3365
3366   info->realized = FALSE;
3367
3368 }
3369
3370 /**
3371  * gtk_window_set_icon_list:
3372  * @window: a #GtkWindow
3373  * @list: list of #GdkPixbuf
3374  *
3375  * Sets up the icon representing a #GtkWindow. The icon is used when
3376  * the window is minimized (also known as iconified).  Some window
3377  * managers or desktop environments may also place it in the window
3378  * frame, or display it in other contexts.
3379  *
3380  * gtk_window_set_icon_list() allows you to pass in the same icon in
3381  * several hand-drawn sizes. The list should contain the natural sizes
3382  * your icon is available in; that is, don't scale the image before
3383  * passing it to GTK+. Scaling is postponed until the last minute,
3384  * when the desired final size is known, to allow best quality.
3385  *
3386  * By passing several sizes, you may improve the final image quality
3387  * of the icon, by reducing or eliminating automatic image scaling.
3388  *
3389  * Recommended sizes to provide: 16x16, 32x32, 48x48 at minimum, and
3390  * larger images (64x64, 128x128) if you have them.
3391  *
3392  * See also gtk_window_set_default_icon_list() to set the icon
3393  * for all windows in your application in one go.
3394  *
3395  * Note that transient windows (those who have been set transient for another
3396  * window using gtk_window_set_transient_for()) will inherit their
3397  * icon from their transient parent. So there's no need to explicitly
3398  * set the icon on transient windows.
3399  **/
3400 void
3401 gtk_window_set_icon_list (GtkWindow  *window,
3402                           GList      *list)
3403 {
3404   GtkWindowIconInfo *info;
3405
3406   g_return_if_fail (GTK_IS_WINDOW (window));
3407
3408   info = ensure_icon_info (window);
3409
3410   if (info->icon_list == list) /* check for NULL mostly */
3411     return;
3412
3413   g_list_foreach (list,
3414                   (GFunc) g_object_ref, NULL);
3415
3416   g_list_foreach (info->icon_list,
3417                   (GFunc) g_object_unref, NULL);
3418
3419   g_list_free (info->icon_list);
3420
3421   info->icon_list = g_list_copy (list);
3422
3423   g_object_notify (G_OBJECT (window), "icon");
3424   
3425   gtk_window_unrealize_icon (window);
3426   
3427   if (GTK_WIDGET_REALIZED (window))
3428     gtk_window_realize_icon (window);
3429
3430   /* We could try to update our transient children, but I don't think
3431    * it's really worth it. If we did it, the best way would probably
3432    * be to have children connect to notify::icon-list
3433    */
3434 }
3435
3436 /**
3437  * gtk_window_get_icon_list:
3438  * @window: a #GtkWindow
3439  * 
3440  * Retrieves the list of icons set by gtk_window_set_icon_list().
3441  * The list is copied, but the reference count on each
3442  * member won't be incremented.
3443  *
3444  * Return value: (element-type GdkPixbuf) (transfer container): copy of window's icon list
3445  **/
3446 GList*
3447 gtk_window_get_icon_list (GtkWindow  *window)
3448 {
3449   GtkWindowIconInfo *info;
3450   
3451   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3452
3453   info = get_icon_info (window);
3454
3455   if (info)
3456     return g_list_copy (info->icon_list);
3457   else
3458     return NULL;  
3459 }
3460
3461 /**
3462  * gtk_window_set_icon:
3463  * @window: a #GtkWindow
3464  * @icon: (allow-none): icon image, or %NULL
3465  *
3466  * Sets up the icon representing a #GtkWindow. This icon is used when
3467  * the window is minimized (also known as iconified).  Some window
3468  * managers or desktop environments may also place it in the window
3469  * frame, or display it in other contexts.
3470  *
3471  * The icon should be provided in whatever size it was naturally
3472  * drawn; that is, don't scale the image before passing it to
3473  * GTK+. Scaling is postponed until the last minute, when the desired
3474  * final size is known, to allow best quality.
3475  *
3476  * If you have your icon hand-drawn in multiple sizes, use
3477  * gtk_window_set_icon_list(). Then the best size will be used.
3478  *
3479  * This function is equivalent to calling gtk_window_set_icon_list()
3480  * with a 1-element list.
3481  *
3482  * See also gtk_window_set_default_icon_list() to set the icon
3483  * for all windows in your application in one go.
3484  **/
3485 void
3486 gtk_window_set_icon (GtkWindow  *window,
3487                      GdkPixbuf  *icon)
3488 {
3489   GList *list;
3490   
3491   g_return_if_fail (GTK_IS_WINDOW (window));
3492   g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
3493
3494   list = NULL;
3495
3496   if (icon)
3497     list = g_list_append (list, icon);
3498   
3499   gtk_window_set_icon_list (window, list);
3500   g_list_free (list);  
3501 }
3502
3503
3504 static void 
3505 update_themed_icon (GtkIconTheme *icon_theme,
3506                     GtkWindow    *window)
3507 {
3508   g_object_notify (G_OBJECT (window), "icon");
3509   
3510   gtk_window_unrealize_icon (window);
3511   
3512   if (GTK_WIDGET_REALIZED (window))
3513     gtk_window_realize_icon (window);  
3514 }
3515
3516 /**
3517  * gtk_window_set_icon_name:
3518  * @window: a #GtkWindow
3519  * @name: (allow-none): the name of the themed icon
3520  *
3521  * Sets the icon for the window from a named themed icon. See
3522  * the docs for #GtkIconTheme for more details.
3523  *
3524  * Note that this has nothing to do with the WM_ICON_NAME 
3525  * property which is mentioned in the ICCCM.
3526  *
3527  * Since: 2.6
3528  */
3529 void 
3530 gtk_window_set_icon_name (GtkWindow   *window,
3531                           const gchar *name)
3532 {
3533   GtkWindowIconInfo *info;
3534   gchar *tmp;
3535   
3536   g_return_if_fail (GTK_IS_WINDOW (window));
3537
3538   info = ensure_icon_info (window);
3539
3540   if (g_strcmp0 (info->icon_name, name) == 0)
3541     return;
3542
3543   tmp = info->icon_name;
3544   info->icon_name = g_strdup (name);
3545   g_free (tmp);
3546
3547   g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
3548   g_list_free (info->icon_list);
3549   info->icon_list = NULL;
3550   
3551   update_themed_icon (NULL, window);
3552
3553   g_object_notify (G_OBJECT (window), "icon-name");
3554 }
3555
3556 /**
3557  * gtk_window_get_icon_name:
3558  * @window: a #GtkWindow
3559  *
3560  * Returns the name of the themed icon for the window,
3561  * see gtk_window_set_icon_name().
3562  *
3563  * Returns: the icon name or %NULL if the window has 
3564  * no themed icon
3565  *
3566  * Since: 2.6
3567  */
3568 const gchar *
3569 gtk_window_get_icon_name (GtkWindow *window)
3570 {
3571   GtkWindowIconInfo *info;
3572
3573   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3574
3575   info = ensure_icon_info (window);
3576
3577   return info->icon_name;
3578 }
3579
3580 /**
3581  * gtk_window_get_icon:
3582  * @window: a #GtkWindow
3583  * 
3584  * Gets the value set by gtk_window_set_icon() (or if you've
3585  * called gtk_window_set_icon_list(), gets the first icon in
3586  * the icon list).
3587  *
3588  * Return value: (transfer none): icon for window
3589  **/
3590 GdkPixbuf*
3591 gtk_window_get_icon (GtkWindow  *window)
3592 {
3593   GtkWindowIconInfo *info;
3594
3595   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
3596
3597   info = get_icon_info (window);
3598   if (info && info->icon_list)
3599     return GDK_PIXBUF (info->icon_list->data);
3600   else
3601     return NULL;
3602 }
3603
3604 /* Load pixbuf, printing warning on failure if error == NULL
3605  */
3606 static GdkPixbuf *
3607 load_pixbuf_verbosely (const char *filename,
3608                        GError    **err)
3609 {
3610   GError *local_err = NULL;
3611   GdkPixbuf *pixbuf;
3612
3613   pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
3614
3615   if (!pixbuf)
3616     {
3617       if (err)
3618         *err = local_err;
3619       else
3620         {
3621           g_warning ("Error loading icon from file '%s':\n\t%s",
3622                      filename, local_err->message);
3623           g_error_free (local_err);
3624         }
3625     }
3626
3627   return pixbuf;
3628 }
3629
3630 /**
3631  * gtk_window_set_icon_from_file:
3632  * @window: a #GtkWindow
3633  * @filename: location of icon file
3634  * @err: (allow-none): location to store error, or %NULL.
3635  *
3636  * Sets the icon for @window.  
3637  * Warns on failure if @err is %NULL.
3638  *
3639  * This function is equivalent to calling gtk_window_set_icon()
3640  * with a pixbuf created by loading the image from @filename.
3641  *
3642  * Returns: %TRUE if setting the icon succeeded.
3643  *
3644  * Since: 2.2
3645  **/
3646 gboolean
3647 gtk_window_set_icon_from_file (GtkWindow   *window,
3648                                const gchar *filename,
3649                                GError     **err)
3650 {
3651   GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3652
3653   if (pixbuf)
3654     {
3655       gtk_window_set_icon (window, pixbuf);
3656       g_object_unref (pixbuf);
3657       
3658       return TRUE;
3659     }
3660   else
3661     return FALSE;
3662 }
3663
3664 /**
3665  * gtk_window_set_default_icon_list:
3666  * @list: a list of #GdkPixbuf
3667  *
3668  * Sets an icon list to be used as fallback for windows that haven't
3669  * had gtk_window_set_icon_list() called on them to set up a
3670  * window-specific icon list. This function allows you to set up the
3671  * icon for all windows in your app at once.
3672  *
3673  * See gtk_window_set_icon_list() for more details.
3674  * 
3675  **/
3676 void
3677 gtk_window_set_default_icon_list (GList *list)
3678 {
3679   GList *toplevels;
3680   GList *tmp_list;
3681   if (list == default_icon_list)
3682     return;
3683
3684   /* Update serial so we don't used cached pixmaps/masks
3685    */
3686   default_icon_serial++;
3687   
3688   g_list_foreach (list,
3689                   (GFunc) g_object_ref, NULL);
3690
3691   g_list_foreach (default_icon_list,
3692                   (GFunc) g_object_unref, NULL);
3693
3694   g_list_free (default_icon_list);
3695
3696   default_icon_list = g_list_copy (list);
3697   
3698   /* Update all toplevels */
3699   toplevels = gtk_window_list_toplevels ();
3700   tmp_list = toplevels;
3701   while (tmp_list != NULL)
3702     {
3703       GtkWindowIconInfo *info;
3704       GtkWindow *w = tmp_list->data;
3705       
3706       info = get_icon_info (w);
3707       if (info && info->using_default_icon)
3708         {
3709           gtk_window_unrealize_icon (w);
3710           if (GTK_WIDGET_REALIZED (w))
3711             gtk_window_realize_icon (w);
3712         }
3713
3714       tmp_list = tmp_list->next;
3715     }
3716   g_list_free (toplevels);
3717 }
3718
3719 /**
3720  * gtk_window_set_default_icon:
3721  * @icon: the icon
3722  *
3723  * Sets an icon to be used as fallback for windows that haven't
3724  * had gtk_window_set_icon() called on them from a pixbuf.
3725  *
3726  * Since: 2.4
3727  **/
3728 void
3729 gtk_window_set_default_icon (GdkPixbuf *icon)
3730 {
3731   GList *list;
3732   
3733   g_return_if_fail (GDK_IS_PIXBUF (icon));
3734
3735   list = g_list_prepend (NULL, icon);
3736   gtk_window_set_default_icon_list (list);
3737   g_list_free (list);
3738 }
3739
3740 /**
3741  * gtk_window_set_default_icon_name:
3742  * @name: the name of the themed icon
3743  *
3744  * Sets an icon to be used as fallback for windows that haven't
3745  * had gtk_window_set_icon_list() called on them from a named
3746  * themed icon, see gtk_window_set_icon_name().
3747  *
3748  * Since: 2.6
3749  **/
3750 void
3751 gtk_window_set_default_icon_name (const gchar *name)
3752 {
3753   GList *tmp_list;
3754   GList *toplevels;
3755
3756   /* Update serial so we don't used cached pixmaps/masks
3757    */
3758   default_icon_serial++;
3759
3760   g_free (default_icon_name);
3761   default_icon_name = g_strdup (name);
3762
3763   g_list_foreach (default_icon_list,
3764                   (GFunc) g_object_unref, NULL);
3765
3766   g_list_free (default_icon_list);
3767   default_icon_list = NULL;
3768   
3769   /* Update all toplevels */
3770   toplevels = gtk_window_list_toplevels ();
3771   tmp_list = toplevels;
3772   while (tmp_list != NULL)
3773     {
3774       GtkWindowIconInfo *info;
3775       GtkWindow *w = tmp_list->data;
3776       
3777       info = get_icon_info (w);
3778       if (info && info->using_default_icon && info->using_themed_icon)
3779         {
3780           gtk_window_unrealize_icon (w);
3781           if (GTK_WIDGET_REALIZED (w))
3782             gtk_window_realize_icon (w);
3783         }
3784
3785       tmp_list = tmp_list->next;
3786     }
3787   g_list_free (toplevels);
3788 }
3789
3790 /**
3791  * gtk_window_get_default_icon_name:
3792  *
3793  * Returns the fallback icon name for windows that has been set
3794  * with gtk_window_set_default_icon_name(). The returned
3795  * string is owned by GTK+ and should not be modified. It
3796  * is only valid until the next call to
3797  * gtk_window_set_default_icon_name().
3798  *
3799  * Returns: the fallback icon name for windows
3800  *
3801  * Since: 2.16
3802  */
3803 const gchar *
3804 gtk_window_get_default_icon_name (void)
3805 {
3806   return default_icon_name;
3807 }
3808
3809 /**
3810  * gtk_window_set_default_icon_from_file:
3811  * @filename: location of icon file
3812  * @err: (allow-none): location to store error, or %NULL.
3813  *
3814  * Sets an icon to be used as fallback for windows that haven't
3815  * had gtk_window_set_icon_list() called on them from a file
3816  * on disk. Warns on failure if @err is %NULL.
3817  *
3818  * Returns: %TRUE if setting the icon succeeded.
3819  *
3820  * Since: 2.2
3821  **/
3822 gboolean
3823 gtk_window_set_default_icon_from_file (const gchar *filename,
3824                                        GError     **err)
3825 {
3826   GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
3827
3828   if (pixbuf)
3829     {
3830       gtk_window_set_default_icon (pixbuf);
3831       g_object_unref (pixbuf);
3832       
3833       return TRUE;
3834     }
3835   else
3836     return FALSE;
3837 }
3838
3839 /**
3840  * gtk_window_get_default_icon_list:
3841  * 
3842  * Gets the value set by gtk_window_set_default_icon_list().
3843  * The list is a copy and should be freed with g_list_free(),
3844  * but the pixbufs in the list have not had their reference count
3845  * incremented.
3846  * 
3847  * Return value: copy of default icon list 
3848  **/
3849 GList*
3850 gtk_window_get_default_icon_list (void)
3851 {
3852   return g_list_copy (default_icon_list);
3853 }
3854
3855 static void
3856 gtk_window_set_default_size_internal (GtkWindow    *window,
3857                                       gboolean      change_width,
3858                                       gint          width,
3859                                       gboolean      change_height,
3860                                       gint          height,
3861                                       gboolean      is_geometry)
3862 {
3863   GtkWindowGeometryInfo *info;
3864
3865   g_return_if_fail (change_width == FALSE || width >= -1);
3866   g_return_if_fail (change_height == FALSE || height >= -1);
3867
3868   info = gtk_window_get_geometry_info (window, TRUE);
3869
3870   g_object_freeze_notify (G_OBJECT (window));
3871
3872   info->default_is_geometry = is_geometry != FALSE;
3873
3874   if (change_width)
3875     {
3876       if (width == 0)
3877         width = 1;
3878
3879       if (width < 0)
3880         width = -1;
3881
3882       info->default_width = width;
3883
3884       g_object_notify (G_OBJECT (window), "default-width");
3885     }
3886
3887   if (change_height)
3888     {
3889       if (height == 0)
3890         height = 1;
3891
3892       if (height < 0)
3893         height = -1;
3894
3895       info->default_height = height;
3896       
3897       g_object_notify (G_OBJECT (window), "default-height");
3898     }
3899   
3900   g_object_thaw_notify (G_OBJECT (window));
3901   
3902   gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
3903 }
3904
3905 /**
3906  * gtk_window_set_default_size:
3907  * @window: a #GtkWindow
3908  * @width: width in pixels, or -1 to unset the default width
3909  * @height: height in pixels, or -1 to unset the default height
3910  *
3911  * Sets the default size of a window. If the window's "natural" size
3912  * (its size request) is larger than the default, the default will be
3913  * ignored. More generally, if the default size does not obey the
3914  * geometry hints for the window (gtk_window_set_geometry_hints() can
3915  * be used to set these explicitly), the default size will be clamped
3916  * to the nearest permitted size.
3917  * 
3918  * Unlike gtk_widget_set_size_request(), which sets a size request for
3919  * a widget and thus would keep users from shrinking the window, this
3920  * function only sets the initial size, just as if the user had
3921  * resized the window themselves. Users can still shrink the window
3922  * again as they normally would. Setting a default size of -1 means to
3923  * use the "natural" default size (the size request of the window).
3924  *
3925  * For more control over a window's initial size and how resizing works,
3926  * investigate gtk_window_set_geometry_hints().
3927  *
3928  * For some uses, gtk_window_resize() is a more appropriate function.
3929  * gtk_window_resize() changes the current size of the window, rather
3930  * than the size to be used on initial display. gtk_window_resize() always
3931  * affects the window itself, not the geometry widget.
3932  *
3933  * The default size of a window only affects the first time a window is
3934  * shown; if a window is hidden and re-shown, it will remember the size
3935  * it had prior to hiding, rather than using the default size.
3936  *
3937  * Windows can't actually be 0x0 in size, they must be at least 1x1, but
3938  * passing 0 for @width and @height is OK, resulting in a 1x1 default size.
3939  **/
3940 void       
3941 gtk_window_set_default_size (GtkWindow   *window,
3942                              gint         width,
3943                              gint         height)
3944 {
3945   g_return_if_fail (GTK_IS_WINDOW (window));
3946   g_return_if_fail (width >= -1);
3947   g_return_if_fail (height >= -1);
3948
3949   gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
3950 }
3951
3952 /**
3953  * gtk_window_get_default_size:
3954  * @window: a #GtkWindow
3955  * @width: (allow-none): location to store the default width, or %NULL
3956  * @height: (allow-none): location to store the default height, or %NULL
3957  *
3958  * Gets the default size of the window. A value of -1 for the width or
3959  * height indicates that a default size has not been explicitly set
3960  * for that dimension, so the "natural" size of the window will be
3961  * used.
3962  * 
3963  **/
3964 void
3965 gtk_window_get_default_size (GtkWindow *window,
3966                              gint      *width,
3967                              gint      *height)
3968 {
3969   GtkWindowGeometryInfo *info;
3970
3971   g_return_if_fail (GTK_IS_WINDOW (window));
3972
3973   info = gtk_window_get_geometry_info (window, FALSE);
3974
3975   if (width)
3976     *width = info ? info->default_width : -1;
3977
3978   if (height)
3979     *height = info ? info->default_height : -1;
3980 }
3981
3982 /**
3983  * gtk_window_resize:
3984  * @window: a #GtkWindow
3985  * @width: width in pixels to resize the window to
3986  * @height: height in pixels to resize the window to
3987  *
3988  * Resizes the window as if the user had done so, obeying geometry
3989  * constraints. The default geometry constraint is that windows may
3990  * not be smaller than their size request; to override this
3991  * constraint, call gtk_widget_set_size_request() to set the window's
3992  * request to a smaller value.
3993  *
3994  * If gtk_window_resize() is called before showing a window for the
3995  * first time, it overrides any default size set with
3996  * gtk_window_set_default_size().
3997  *
3998  * Windows may not be resized smaller than 1 by 1 pixels.
3999  * 
4000  **/
4001 void
4002 gtk_window_resize (GtkWindow *window,
4003                    gint       width,
4004                    gint       height)
4005 {
4006   GtkWindowGeometryInfo *info;
4007   
4008   g_return_if_fail (GTK_IS_WINDOW (window));
4009   g_return_if_fail (width > 0);
4010   g_return_if_fail (height > 0);
4011
4012   info = gtk_window_get_geometry_info (window, TRUE);
4013
4014   info->resize_width = width;
4015   info->resize_height = height;
4016
4017   gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
4018 }
4019
4020 /**
4021  * gtk_window_get_size:
4022  * @window: a #GtkWindow
4023  * @width: (allow-none): (out): return location for width, or %NULL
4024  * @height: (allow-none): (out): return location for height, or %NULL
4025  *
4026  * Obtains the current size of @window. If @window is not onscreen,
4027  * it returns the size GTK+ will suggest to the <link
4028  * linkend="gtk-X11-arch">window manager</link> for the initial window
4029  * size (but this is not reliably the same as the size the window
4030  * manager will actually select). The size obtained by
4031  * gtk_window_get_size() is the last size received in a
4032  * #GdkEventConfigure, that is, GTK+ uses its locally-stored size,
4033  * rather than querying the X server for the size. As a result, if you
4034  * call gtk_window_resize() then immediately call
4035  * gtk_window_get_size(), the size won't have taken effect yet. After
4036  * the window manager processes the resize request, GTK+ receives
4037  * notification that the size has changed via a configure event, and
4038  * the size of the window gets updated.
4039  *
4040  * Note 1: Nearly any use of this function creates a race condition,
4041  * because the size of the window may change between the time that you
4042  * get the size and the time that you perform some action assuming
4043  * that size is the current size. To avoid race conditions, connect to
4044  * "configure-event" on the window and adjust your size-dependent
4045  * state to match the size delivered in the #GdkEventConfigure.
4046  *
4047  * Note 2: The returned size does <emphasis>not</emphasis> include the
4048  * size of the window manager decorations (aka the window frame or
4049  * border). Those are not drawn by GTK+ and GTK+ has no reliable
4050  * method of determining their size.
4051  *
4052  * Note 3: If you are getting a window size in order to position
4053  * the window onscreen, there may be a better way. The preferred
4054  * way is to simply set the window's semantic type with
4055  * gtk_window_set_type_hint(), which allows the window manager to
4056  * e.g. center dialogs. Also, if you set the transient parent of
4057  * dialogs with gtk_window_set_transient_for() window managers
4058  * will often center the dialog over its parent window. It's
4059  * much preferred to let the window manager handle these
4060  * things rather than doing it yourself, because all apps will
4061  * behave consistently and according to user prefs if the window
4062  * manager handles it. Also, the window manager can take the size
4063  * of the window decorations/border into account, while your
4064  * application cannot.
4065  *
4066  * In any case, if you insist on application-specified window
4067  * positioning, there's <emphasis>still</emphasis> a better way than
4068  * doing it yourself - gtk_window_set_position() will frequently
4069  * handle the details for you.
4070  * 
4071  **/
4072 void
4073 gtk_window_get_size (GtkWindow *window,
4074                      gint      *width,
4075                      gint      *height)
4076 {
4077   gint w, h;
4078   
4079   g_return_if_fail (GTK_IS_WINDOW (window));
4080
4081   if (width == NULL && height == NULL)
4082     return;
4083
4084   if (gtk_widget_get_mapped (GTK_WIDGET (window)))
4085     {
4086       gdk_drawable_get_size (GTK_WIDGET (window)->window,
4087                              &w, &h);
4088     }
4089   else
4090     {
4091       GdkRectangle configure_request;
4092
4093       gtk_window_compute_configure_request (window,
4094                                             &configure_request,
4095                                             NULL, NULL);
4096
4097       w = configure_request.width;
4098       h = configure_request.height;
4099     }
4100   
4101   if (width)
4102     *width = w;
4103   if (height)
4104     *height = h;
4105 }
4106
4107 /**
4108  * gtk_window_move:
4109  * @window: a #GtkWindow
4110  * @x: X coordinate to move window to
4111  * @y: Y coordinate to move window to
4112  *
4113  * Asks the <link linkend="gtk-X11-arch">window manager</link> to move
4114  * @window to the given position.  Window managers are free to ignore
4115  * this; most window managers ignore requests for initial window
4116  * positions (instead using a user-defined placement algorithm) and
4117  * honor requests after the window has already been shown.
4118  *
4119  * Note: the position is the position of the gravity-determined
4120  * reference point for the window. The gravity determines two things:
4121  * first, the location of the reference point in root window
4122  * coordinates; and second, which point on the window is positioned at
4123  * the reference point.
4124  *
4125  * By default the gravity is #GDK_GRAVITY_NORTH_WEST, so the reference
4126  * point is simply the @x, @y supplied to gtk_window_move(). The
4127  * top-left corner of the window decorations (aka window frame or
4128  * border) will be placed at @x, @y.  Therefore, to position a window
4129  * at the top left of the screen, you want to use the default gravity
4130  * (which is #GDK_GRAVITY_NORTH_WEST) and move the window to 0,0.
4131  *
4132  * To position a window at the bottom right corner of the screen, you
4133  * would set #GDK_GRAVITY_SOUTH_EAST, which means that the reference
4134  * point is at @x + the window width and @y + the window height, and
4135  * the bottom-right corner of the window border will be placed at that
4136  * reference point. So, to place a window in the bottom right corner
4137  * you would first set gravity to south east, then write:
4138  * <literal>gtk_window_move (window, gdk_screen_width () - window_width,
4139  * gdk_screen_height () - window_height)</literal> (note that this
4140  * example does not take multi-head scenarios into account).
4141  *
4142  * The Extended Window Manager Hints specification at <ulink 
4143  * url="http://www.freedesktop.org/Standards/wm-spec">
4144  * http://www.freedesktop.org/Standards/wm-spec</ulink> has a 
4145  * nice table of gravities in the "implementation notes" section.
4146  *
4147  * The gtk_window_get_position() documentation may also be relevant.
4148  */
4149 void
4150 gtk_window_move (GtkWindow *window,
4151                  gint       x,
4152                  gint       y)
4153 {
4154   GtkWindowGeometryInfo *info;
4155   GtkWidget *widget;
4156   
4157   g_return_if_fail (GTK_IS_WINDOW (window));
4158
4159   widget = GTK_WIDGET (window);
4160
4161   info = gtk_window_get_geometry_info (window, TRUE);  
4162   
4163   if (gtk_widget_get_mapped (widget))
4164     {
4165       /* we have now sent a request with this position
4166        * with currently-active constraints, so toggle flag.
4167        */
4168       info->position_constraints_changed = FALSE;
4169
4170       /* we only constrain if mapped - if not mapped,
4171        * then gtk_window_compute_configure_request()
4172        * will apply the constraints later, and we
4173        * don't want to lose information about
4174        * what position the user set before then.
4175        * i.e. if you do a move() then turn off POS_CENTER
4176        * then show the window, your move() will work.
4177        */
4178       gtk_window_constrain_position (window,
4179                                      widget->allocation.width,
4180                                      widget->allocation.height,
4181                                      &x, &y);
4182       
4183       /* Note that this request doesn't go through our standard request
4184        * framework, e.g. doesn't increment configure_request_count,
4185        * doesn't set info->last, etc.; that's because
4186        * we don't save the info needed to arrive at this same request
4187        * again.
4188        *
4189        * To gtk_window_move_resize(), this will end up looking exactly
4190        * the same as the position being changed by the window
4191        * manager.
4192        */
4193       
4194       /* FIXME are we handling gravity properly for framed windows? */
4195       if (window->frame)
4196         gdk_window_move (window->frame,
4197                          x - window->frame_left,
4198                          y - window->frame_top);
4199       else
4200         gdk_window_move (GTK_WIDGET (window)->window,
4201                          x, y);
4202     }
4203   else
4204     {
4205       /* Save this position to apply on mapping */
4206       info->initial_x = x;
4207       info->initial_y = y;
4208       info->initial_pos_set = TRUE;
4209     }
4210 }
4211
4212 /**
4213  * gtk_window_get_position:
4214  * @window: a #GtkWindow
4215  * @root_x: return location for X coordinate of gravity-determined reference point
4216  * @root_y: return location for Y coordinate of gravity-determined reference point
4217  *
4218  * This function returns the position you need to pass to
4219  * gtk_window_move() to keep @window in its current position.  This
4220  * means that the meaning of the returned value varies with window
4221  * gravity. See gtk_window_move() for more details.
4222  * 
4223  * If you haven't changed the window gravity, its gravity will be
4224  * #GDK_GRAVITY_NORTH_WEST. This means that gtk_window_get_position()
4225  * gets the position of the top-left corner of the window manager
4226  * frame for the window. gtk_window_move() sets the position of this
4227  * same top-left corner.
4228  *
4229  * gtk_window_get_position() is not 100% reliable because the X Window System
4230  * does not specify a way to obtain the geometry of the
4231  * decorations placed on a window by the window manager.
4232  * Thus GTK+ is using a "best guess" that works with most
4233  * window managers.
4234  *
4235  * Moreover, nearly all window managers are historically broken with
4236  * respect to their handling of window gravity. So moving a window to
4237  * its current position as returned by gtk_window_get_position() tends
4238  * to result in moving the window slightly. Window managers are
4239  * slowly getting better over time.
4240  *
4241  * If a window has gravity #GDK_GRAVITY_STATIC the window manager
4242  * frame is not relevant, and thus gtk_window_get_position() will
4243  * always produce accurate results. However you can't use static
4244  * gravity to do things like place a window in a corner of the screen,
4245  * because static gravity ignores the window manager decorations.
4246  *
4247  * If you are saving and restoring your application's window
4248  * positions, you should know that it's impossible for applications to
4249  * do this without getting it somewhat wrong because applications do
4250  * not have sufficient knowledge of window manager state. The Correct
4251  * Mechanism is to support the session management protocol (see the
4252  * "GnomeClient" object in the GNOME libraries for example) and allow
4253  * the window manager to save your window sizes and positions.
4254  * 
4255  **/
4256
4257 void
4258 gtk_window_get_position (GtkWindow *window,
4259                          gint      *root_x,
4260                          gint      *root_y)
4261 {
4262   GtkWidget *widget;
4263
4264   g_return_if_fail (GTK_IS_WINDOW (window));
4265
4266   widget = GTK_WIDGET (window);
4267   
4268   if (window->gravity == GDK_GRAVITY_STATIC)
4269     {
4270       if (gtk_widget_get_mapped (widget))
4271         {
4272           /* This does a server round-trip, which is sort of wrong;
4273            * but a server round-trip is inevitable for
4274            * gdk_window_get_frame_extents() in the usual
4275            * NorthWestGravity case below, so not sure what else to
4276            * do. We should likely be consistent about whether we get
4277            * the client-side info or the server-side info.
4278            */
4279           gdk_window_get_origin (widget->window, root_x, root_y);
4280         }
4281       else
4282         {
4283           GdkRectangle configure_request;
4284           
4285           gtk_window_compute_configure_request (window,
4286                                                 &configure_request,
4287                                                 NULL, NULL);
4288           
4289           *root_x = configure_request.x;
4290           *root_y = configure_request.y;
4291         }
4292     }
4293   else
4294     {
4295       GdkRectangle frame_extents;
4296       
4297       gint x, y;
4298       gint w, h;
4299       
4300       if (gtk_widget_get_mapped (widget))
4301         {
4302           if (window->frame)
4303             gdk_window_get_frame_extents (window->frame, &frame_extents);
4304           else
4305             gdk_window_get_frame_extents (widget->window, &frame_extents);
4306           x = frame_extents.x;
4307           y = frame_extents.y;
4308           gtk_window_get_size (window, &w, &h);
4309         }
4310       else
4311         {
4312           /* We just say the frame has 0 size on all sides.
4313            * Not sure what else to do.
4314            */             
4315           gtk_window_compute_configure_request (window,
4316                                                 &frame_extents,
4317                                                 NULL, NULL);
4318           x = frame_extents.x;
4319           y = frame_extents.y;
4320           w = frame_extents.width;
4321           h = frame_extents.height;
4322         }
4323       
4324       switch (window->gravity)
4325         {
4326         case GDK_GRAVITY_NORTH:
4327         case GDK_GRAVITY_CENTER:
4328         case GDK_GRAVITY_SOUTH:
4329           /* Find center of frame. */
4330           x += frame_extents.width / 2;
4331           /* Center client window on that point. */
4332           x -= w / 2;
4333           break;
4334
4335         case GDK_GRAVITY_SOUTH_EAST:
4336         case GDK_GRAVITY_EAST:
4337         case GDK_GRAVITY_NORTH_EAST:
4338           /* Find right edge of frame */
4339           x += frame_extents.width;
4340           /* Align left edge of client at that point. */
4341           x -= w;
4342           break;
4343         default:
4344           break;
4345         }
4346
4347       switch (window->gravity)
4348         {
4349         case GDK_GRAVITY_WEST:
4350         case GDK_GRAVITY_CENTER:
4351         case GDK_GRAVITY_EAST:
4352           /* Find center of frame. */
4353           y += frame_extents.height / 2;
4354           /* Center client window there. */
4355           y -= h / 2;
4356           break;
4357         case GDK_GRAVITY_SOUTH_WEST:
4358         case GDK_GRAVITY_SOUTH:
4359         case GDK_GRAVITY_SOUTH_EAST:
4360           /* Find south edge of frame */
4361           y += frame_extents.height;
4362           /* Place bottom edge of client there */
4363           y -= h;
4364           break;
4365         default:
4366           break;
4367         }
4368       
4369       if (root_x)
4370         *root_x = x;
4371       if (root_y)
4372         *root_y = y;
4373     }
4374 }
4375
4376 /**
4377  * gtk_window_reshow_with_initial_size:
4378  * @window: a #GtkWindow
4379  * 
4380  * Hides @window, then reshows it, resetting the
4381  * default size and position of the window. Used
4382  * by GUI builders only.
4383  **/
4384 void
4385 gtk_window_reshow_with_initial_size (GtkWindow *window)
4386 {
4387   GtkWidget *widget;
4388   
4389   g_return_if_fail (GTK_IS_WINDOW (window));
4390
4391   widget = GTK_WIDGET (window);
4392   
4393   gtk_widget_hide (widget);
4394   gtk_widget_unrealize (widget);
4395   gtk_widget_show (widget);
4396 }
4397
4398 static void
4399 gtk_window_destroy (GtkObject *object)
4400 {
4401   GtkWindow *window = GTK_WINDOW (object);
4402   
4403   toplevel_list = g_slist_remove (toplevel_list, window);
4404
4405   if (window->transient_parent)
4406     gtk_window_set_transient_for (window, NULL);
4407
4408   /* frees the icons */
4409   gtk_window_set_icon_list (window, NULL);
4410   
4411   if (window->has_user_ref_count)
4412     {
4413       window->has_user_ref_count = FALSE;
4414       g_object_unref (window);
4415     }
4416
4417   if (window->group)
4418     gtk_window_group_remove_window (window->group, window);
4419
4420    gtk_window_free_key_hash (window);
4421
4422    GTK_OBJECT_CLASS (gtk_window_parent_class)->destroy (object);
4423 }
4424
4425 static void
4426 gtk_window_finalize (GObject *object)
4427 {
4428   GtkWindow *window = GTK_WINDOW (object);
4429   GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
4430   GtkMnemonicHash *mnemonic_hash;
4431
4432   g_free (window->title);
4433   g_free (window->wmclass_name);
4434   g_free (window->wmclass_class);
4435   g_free (window->wm_role);
4436
4437   mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
4438   if (mnemonic_hash)
4439     _gtk_mnemonic_hash_free (mnemonic_hash);
4440
4441   if (window->geometry_info)
4442     {
4443       if (window->geometry_info->widget)
4444         g_signal_handlers_disconnect_by_func (window->geometry_info->widget,
4445                                               gtk_widget_destroyed,
4446                                               &window->geometry_info->widget);
4447       g_free (window->geometry_info);
4448     }
4449
4450   if (window->keys_changed_handler)
4451     {
4452       g_source_remove (window->keys_changed_handler);
4453       window->keys_changed_handler = 0;
4454     }
4455
4456   if (window->screen)
4457     g_signal_handlers_disconnect_by_func (window->screen,
4458                                           gtk_window_on_composited_changed, window);
4459
4460   g_free (priv->startup_id);
4461
4462   G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
4463 }
4464
4465 static void
4466 gtk_window_show (GtkWidget *widget)
4467 {
4468   GtkWindow *window = GTK_WINDOW (widget);
4469   GtkContainer *container = GTK_CONTAINER (window);
4470   gboolean need_resize;
4471
4472   GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
4473   
4474   need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
4475   container->need_resize = FALSE;
4476
4477   if (need_resize)
4478     {
4479       GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
4480       GtkAllocation allocation = { 0, 0 };
4481       GdkRectangle configure_request;
4482       GdkGeometry new_geometry;
4483       guint new_flags;
4484       gboolean was_realized;
4485
4486       /* We are going to go ahead and perform this configure request
4487        * and then emulate a configure notify by going ahead and
4488        * doing a size allocate. Sort of a synchronous
4489        * mini-copy of gtk_window_move_resize() here.
4490        */
4491       gtk_window_compute_configure_request (window,
4492                                             &configure_request,
4493                                             &new_geometry,
4494                                             &new_flags);
4495       
4496       /* We update this because we are going to go ahead
4497        * and gdk_window_resize() below, rather than
4498        * queuing it.
4499        */
4500       info->last.configure_request.width = configure_request.width;
4501       info->last.configure_request.height = configure_request.height;
4502       
4503       /* and allocate the window - this is normally done
4504        * in move_resize in response to configure notify
4505        */
4506       allocation.width  = configure_request.width;
4507       allocation.height = configure_request.height;
4508       gtk_widget_size_allocate (widget, &allocation);
4509
4510       /* Then we guarantee we have a realize */
4511       was_realized = FALSE;
4512       if (!GTK_WIDGET_REALIZED (widget))
4513         {
4514           gtk_widget_realize (widget);
4515           was_realized = TRUE;
4516         }
4517
4518       /* Must be done after the windows are realized,
4519        * so that the decorations can be read
4520        */
4521       gtk_decorated_window_calculate_frame_size (window);
4522
4523       /* We only send configure request if we didn't just finish
4524        * creating the window; if we just created the window
4525        * then we created it with widget->allocation anyhow.
4526        */
4527       if (!was_realized)
4528         gdk_window_move_resize (widget->window,
4529                                 configure_request.x,
4530                                 configure_request.y,
4531                                 configure_request.width,
4532                                 configure_request.height);
4533     }
4534   
4535   gtk_container_check_resize (container);
4536
4537   gtk_widget_map (widget);
4538
4539   /* Try to make sure that we have some focused widget
4540    */
4541   if (!window->focus_widget && !GTK_IS_PLUG (window))
4542     gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD);
4543   
4544   if (window->modal)
4545     gtk_grab_add (widget);
4546 }
4547
4548 static void
4549 gtk_window_hide (GtkWidget *widget)
4550 {
4551   GtkWindow *window = GTK_WINDOW (widget);
4552
4553   GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
4554   gtk_widget_unmap (widget);
4555
4556   if (window->modal)
4557     gtk_grab_remove (widget);
4558 }
4559
4560 static void
4561 gtk_window_map (GtkWidget *widget)
4562 {
4563   GtkWindow *window = GTK_WINDOW (widget);
4564   GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window);
4565   GdkWindow *toplevel;
4566   gboolean auto_mnemonics;
4567
4568   GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
4569
4570   if (window->bin.child &&
4571       gtk_widget_get_visible (window->bin.child) &&
4572       !gtk_widget_get_mapped (window->bin.child))
4573     gtk_widget_map (window->bin.child);
4574
4575   if (window->frame)
4576     toplevel = window->frame;
4577   else
4578     toplevel = widget->window;
4579   
4580   if (window->maximize_initially)
4581     gdk_window_maximize (toplevel);
4582   else
4583     gdk_window_unmaximize (toplevel);
4584   
4585   if (window->stick_initially)
4586     gdk_window_stick (toplevel);
4587   else
4588     gdk_window_unstick (toplevel);
4589   
4590   if (window->iconify_initially)
4591     gdk_window_iconify (toplevel);
4592   else
4593     gdk_window_deiconify (toplevel);
4594
4595   if (priv->fullscreen_initially)
4596     gdk_window_fullscreen (toplevel);
4597   else
4598     gdk_window_unfullscreen (toplevel);
4599   
4600   gdk_window_set_keep_above (toplevel, priv->above_initially);
4601
4602   gdk_window_set_keep_below (toplevel, priv->below_initially);
4603
4604   /* No longer use the default settings */
4605   window->need_default_size = FALSE;
4606   window->need_default_position = FALSE;
4607   
4608   if (priv->reset_type_hint)
4609     {
4610       /* We should only reset the type hint when the application
4611        * used gtk_window_set_type_hint() to change the hint.
4612        * Some applications use X directly to change the properties;
4613        * in that case, we shouldn't overwrite what they did.
4614        */
4615       gdk_window_set_type_hint (widget->window, priv->type_hint);
4616       priv->reset_type_hint = FALSE;
4617     }
4618
4619   gdk_window_show (widget->window);
4620
4621   if (window->frame)
4622     gdk_window_show (window->frame);
4623
4624   if (!disable_startup_notification)
4625     {
4626       /* Do we have a custom startup-notification id? */
4627       if (priv->startup_id != NULL)
4628         {
4629           /* Make sure we have a "real" id */
4630           if (!startup_id_is_fake (priv->startup_id)) 
4631             gdk_notify_startup_complete_with_id (priv->startup_id);
4632
4633           g_free (priv->startup_id);
4634           priv->startup_id = NULL;
4635         }
4636       else if (!sent_startup_notification)
4637         {
4638           sent_startup_notification = TRUE;
4639           gdk_notify_startup_complete ();
4640         }
4641     }
4642
4643   /* if auto-mnemonics is enabled and mnemonics visible is not already set
4644    * (as in the case of popup menus), then hide mnemonics initially
4645    */
4646   g_object_get (gtk_widget_get_settings (widget), "gtk-auto-mnemonics",
4647                 &auto_mnemonics, NULL);
4648   if (auto_mnemonics && !priv->mnemonics_visible_set)
4649     gtk_window_set_mnemonics_visible (window, FALSE);
4650 }
4651
4652 static gboolean
4653 gtk_window_map_event (GtkWidget   *widget,
4654                       GdkEventAny *event)
4655 {
4656   if (!gtk_widget_get_mapped (widget))
4657     {
4658       /* we should be be unmapped, but are getting a MapEvent, this may happen
4659        * to toplevel XWindows if mapping was intercepted by a window manager
4660        * and an unmap request occoured while the MapRequestEvent was still
4661        * being handled. we work around this situaiton here by re-requesting
4662        * the window being unmapped. more details can be found in:
4663        *   http://bugzilla.gnome.org/show_bug.cgi?id=316180
4664        */
4665       gdk_window_hide (widget->window);
4666     }
4667   return FALSE;
4668 }
4669
4670 static void
4671 gtk_window_unmap (GtkWidget *widget)
4672 {
4673   GtkWindow *window = GTK_WINDOW (widget);
4674   GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (widget);
4675   GtkWindowGeometryInfo *info;    
4676   GdkWindowState state;
4677
4678   GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
4679   if (window->frame)
4680     gdk_window_withdraw (window->frame);
4681   else 
4682     gdk_window_withdraw (widget->window);
4683   
4684   window->configure_request_count = 0;
4685   window->configure_notify_received = FALSE;
4686
4687   /* on unmap, we reset the default positioning of the window,
4688    * so it's placed again, but we don't reset the default
4689    * size of the window, so it's remembered.
4690    */
4691   window->need_default_position = TRUE;
4692
4693   info = gtk_window_get_geometry_info (window, FALSE);
4694   if (info)
4695     {
4696       info->initial_pos_set = FALSE;
4697       info->position_constraints_changed = FALSE;
4698     }
4699
4700   state = gdk_window_get_state (widget->window);
4701   window->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
4702   window->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
4703   window->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
4704   priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
4705   priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
4706 }
4707
4708 static void
4709 gtk_window_realize (GtkWidget *widget)
4710 {
4711   GtkWindow *window;
4712   GdkWindow *parent_window;
4713   GdkWindowAttr attributes;
4714   gint attributes_mask;
4715   GtkWindowPrivate *priv;
4716   
4717   window = GTK_WINDOW (widget);
4718   priv = GTK_WINDOW_GET_PRIVATE (window);
4719
4720   /* ensure widget tree is properly size allocated */
4721   if (widget->allocation.x == -1 &&
4722       widget->allocation.y == -1 &&
4723       widget->allocation.width == 1 &&
4724       widget->allocation.height == 1)
4725     {
4726       GtkRequisition requisition;
4727       GtkAllocation allocation = { 0, 0, 200, 200 };
4728
4729       gtk_widget_size_request (widget, &requisition);
4730       if (requisition.width || requisition.height)
4731         {
4732           /* non-empty window */
4733           allocation.width = requisition.width;
4734           allocation.height = requisition.height;
4735         }
4736       gtk_widget_size_allocate (widget, &allocation);
4737       
4738       _gtk_container_queue_resize (GTK_CONTAINER (widget));
4739
4740       g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
4741     }
4742   
4743   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
4744   
4745   switch (window->type)
4746     {
4747     case GTK_WINDOW_TOPLEVEL:
4748       attributes.window_type = GDK_WINDOW_TOPLEVEL;
4749       break;
4750     case GTK_WINDOW_POPUP:
4751       attributes.window_type = GDK_WINDOW_TEMP;
4752       break;
4753     default:
4754       g_warning (G_STRLOC": Unknown window type %d!", window->type);
4755       break;
4756     }
4757    
4758   attributes.title = window->title;
4759   attributes.wmclass_name = window->wmclass_name;
4760   attributes.wmclass_class = window->wmclass_class;
4761   attributes.wclass = GDK_INPUT_OUTPUT;
4762   attributes.visual = gtk_widget_get_visual (widget);
4763   attributes.colormap = gtk_widget_get_colormap (widget);
4764
4765   if (window->has_frame)
4766     {
4767       attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
4768       attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
4769       attributes.event_mask = (GDK_EXPOSURE_MASK |
4770                                GDK_KEY_PRESS_MASK |
4771                                GDK_ENTER_NOTIFY_MASK |
4772                                GDK_LEAVE_NOTIFY_MASK |
4773                                GDK_FOCUS_CHANGE_MASK |
4774                                GDK_STRUCTURE_MASK |
4775                                GDK_BUTTON_MOTION_MASK |
4776                                GDK_POINTER_MOTION_HINT_MASK |
4777                                GDK_BUTTON_PRESS_MASK |
4778                                GDK_BUTTON_RELEASE_MASK);
4779       
4780       attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
4781       
4782       window->frame = gdk_window_new (gtk_widget_get_root_window (widget),
4783                                       &attributes, attributes_mask);
4784                                                  
4785       if (priv->opacity_set)
4786         gdk_window_set_opacity (window->frame, priv->opacity);
4787
4788       gdk_window_set_user_data (window->frame, widget);
4789       
4790       attributes.window_type = GDK_WINDOW_CHILD;
4791       attributes.x = window->frame_left;
4792       attributes.y = window->frame_top;
4793     
4794       attributes_mask = GDK_WA_X | GDK_WA_Y;
4795
4796       parent_window = window->frame;
4797
4798       g_signal_connect (window,
4799                         "event",
4800                         G_CALLBACK (gtk_window_event),
4801                         NULL);
4802     }
4803   else
4804     {
4805       attributes_mask = 0;
4806       parent_window = gtk_widget_get_root_window (widget);
4807     }
4808   
4809   attributes.width = widget->allocation.width;
4810   attributes.height = widget->allocation.height;
4811   attributes.event_mask = gtk_widget_get_events (widget);
4812   attributes.event_mask |= (GDK_EXPOSURE_MASK |
4813                             GDK_KEY_PRESS_MASK |
4814                             GDK_KEY_RELEASE_MASK |
4815                             GDK_ENTER_NOTIFY_MASK |
4816                             GDK_LEAVE_NOTIFY_MASK |
4817                             GDK_FOCUS_CHANGE_MASK |
4818                             GDK_STRUCTURE_MASK);
4819   attributes.type_hint = priv->type_hint;
4820
4821   attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP | GDK_WA_TYPE_HINT;
4822   attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
4823   attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
4824   
4825   widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
4826
4827   if (!window->has_frame && priv->opacity_set)
4828     gdk_window_set_opacity (widget->window, priv->opacity);
4829
4830   gdk_window_enable_synchronized_configure (widget->window);
4831     
4832   gdk_window_set_user_data (widget->window, window);
4833       
4834   widget->style = gtk_style_attach (widget->style, widget->window);
4835   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
4836   if (window->frame)
4837     gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
4838
4839   /* This is a bad hack to set the window background. */
4840   gtk_window_paint (widget, NULL);
4841   
4842   if (window->transient_parent &&
4843       GTK_WIDGET_REALIZED (window->transient_parent))
4844     gdk_window_set_transient_for (widget->window,
4845                                   GTK_WIDGET (window->transient_parent)->window);
4846
4847   if (window->wm_role)
4848     gdk_window_set_role (widget->window, window->wm_role);
4849   
4850   if (!window->decorated)
4851     gdk_window_set_decorations (widget->window, 0);
4852
4853   if (!priv->deletable)
4854     gdk_window_set_functions (widget->window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
4855
4856   if (gtk_window_get_skip_pager_hint (window))
4857     gdk_window_set_skip_pager_hint (widget->window, TRUE);
4858
4859   if (gtk_window_get_skip_taskbar_hint (window))
4860     gdk_window_set_skip_taskbar_hint (widget->window, TRUE);
4861
4862   if (gtk_window_get_accept_focus (window))
4863     gdk_window_set_accept_focus (widget->window, TRUE);
4864   else
4865     gdk_window_set_accept_focus (widget->window, FALSE);
4866
4867   if (gtk_window_get_focus_on_map (window))
4868     gdk_window_set_focus_on_map (widget->window, TRUE);
4869   else
4870     gdk_window_set_focus_on_map (widget->window, FALSE);
4871   
4872   if (window->modal)
4873     gdk_window_set_modal_hint (widget->window, TRUE);
4874   else
4875     gdk_window_set_modal_hint (widget->window, FALSE);
4876     
4877   if (priv->startup_id)
4878     {
4879 #ifdef GDK_WINDOWING_X11
4880       guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
4881       if (timestamp != GDK_CURRENT_TIME)
4882         gdk_x11_window_set_user_time (widget->window, timestamp);
4883 #endif
4884       if (!startup_id_is_fake (priv->startup_id)) 
4885         gdk_window_set_startup_id (widget->window, priv->startup_id);
4886     }
4887
4888   /* Icons */
4889   gtk_window_realize_icon (window);
4890 }
4891
4892 static void
4893 gtk_window_unrealize (GtkWidget *widget)
4894 {
4895   GtkWindow *window;
4896   GtkWindowGeometryInfo *info;
4897
4898   window = GTK_WINDOW (widget);
4899
4900   /* On unrealize, we reset the size of the window such
4901    * that we will re-apply the default sizing stuff
4902    * next time we show the window.
4903    *
4904    * Default positioning is reset on unmap, instead of unrealize.
4905    */
4906   window->need_default_size = TRUE;
4907   info = gtk_window_get_geometry_info (window, FALSE);
4908   if (info)
4909     {
4910       info->resize_width = -1;
4911       info->resize_height = -1;
4912       info->last.configure_request.x = 0;
4913       info->last.configure_request.y = 0;
4914       info->last.configure_request.width = -1;
4915       info->last.configure_request.height = -1;
4916       /* be sure we reset geom hints on re-realize */
4917       info->last.flags = 0;
4918     }
4919   
4920   if (window->frame)
4921     {
4922       gdk_window_set_user_data (window->frame, NULL);
4923       gdk_window_destroy (window->frame);
4924       window->frame = NULL;
4925     }
4926
4927   /* Icons */
4928   gtk_window_unrealize_icon (window);
4929
4930   GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
4931 }
4932
4933 static void
4934 gtk_window_size_request (GtkWidget      *widget,
4935                          GtkRequisition *requisition)
4936 {
4937   GtkWindow *window;
4938   GtkBin *bin;
4939
4940   window = GTK_WINDOW (widget);
4941   bin = GTK_BIN (window);
4942   
4943   requisition->width = GTK_CONTAINER (window)->border_width * 2;
4944   requisition->height = GTK_CONTAINER (window)->border_width * 2;
4945
4946   if (bin->child && gtk_widget_get_visible (bin->child))
4947     {
4948       GtkRequisition child_requisition;
4949       
4950       gtk_widget_size_request (bin->child, &child_requisition);
4951
4952       requisition->width += child_requisition.width;
4953       requisition->height += child_requisition.height;
4954     }
4955 }
4956
4957 static void
4958 gtk_window_size_allocate (GtkWidget     *widget,
4959                           GtkAllocation *allocation)
4960 {
4961   GtkWindow *window;
4962   GtkAllocation child_allocation;
4963
4964   window = GTK_WINDOW (widget);
4965   widget->allocation = *allocation;
4966
4967   if (window->bin.child && gtk_widget_get_visible (window->bin.child))
4968     {
4969       child_allocation.x = GTK_CONTAINER (window)->border_width;
4970       child_allocation.y = GTK_CONTAINER (window)->border_width;
4971       child_allocation.width =
4972         MAX (1, (gint)allocation->width - child_allocation.x * 2);
4973       child_allocation.height =
4974         MAX (1, (gint)allocation->height - child_allocation.y * 2);
4975
4976       gtk_widget_size_allocate (window->bin.child, &child_allocation);
4977     }
4978
4979   if (GTK_WIDGET_REALIZED (widget) && window->frame)
4980     {
4981       gdk_window_resize (window->frame,
4982                          allocation->width + window->frame_left + window->frame_right,
4983                          allocation->height + window->frame_top + window->frame_bottom);
4984     }
4985 }
4986
4987 static gint
4988 gtk_window_event (GtkWidget *widget, GdkEvent *event)
4989 {
4990   GtkWindow *window;
4991   gboolean return_val;
4992
4993   window = GTK_WINDOW (widget);
4994
4995   if (window->frame && (event->any.window == window->frame))
4996     {
4997       if ((event->type != GDK_KEY_PRESS) &&
4998           (event->type != GDK_KEY_RELEASE) &&
4999           (event->type != GDK_FOCUS_CHANGE))
5000         {
5001           g_signal_stop_emission_by_name (widget, "event");
5002           return_val = FALSE;
5003           g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
5004           return TRUE;
5005         }
5006       else
5007         {
5008           g_object_unref (event->any.window);
5009           event->any.window = g_object_ref (widget->window);
5010         }
5011     }
5012
5013   return FALSE;
5014 }
5015
5016 static gboolean
5017 gtk_window_frame_event (GtkWindow *window, GdkEvent *event)
5018 {
5019   GdkEventConfigure *configure_event;
5020   GdkRectangle rect;
5021
5022   switch (event->type)
5023     {
5024     case GDK_CONFIGURE:
5025       configure_event = (GdkEventConfigure *)event;
5026       
5027       /* Invalidate the decorations */
5028       rect.x = 0;
5029       rect.y = 0;
5030       rect.width = configure_event->width;
5031       rect.height = configure_event->height;
5032       
5033       gdk_window_invalidate_rect (window->frame, &rect, FALSE);
5034
5035       /* Pass on the (modified) configure event */
5036       configure_event->width -= window->frame_left + window->frame_right;
5037       configure_event->height -= window->frame_top + window->frame_bottom;
5038       return gtk_window_configure_event (GTK_WIDGET (window), configure_event);
5039       break;
5040     default:
5041       break;
5042     }
5043   return FALSE;
5044 }
5045
5046 static gint
5047 gtk_window_configure_event (GtkWidget         *widget,
5048                             GdkEventConfigure *event)
5049 {
5050   GtkWindow *window = GTK_WINDOW (widget);
5051   gboolean expected_reply = window->configure_request_count > 0;
5052
5053   /* window->configure_request_count incremented for each 
5054    * configure request, and decremented to a min of 0 for
5055    * each configure notify.
5056    *
5057    * All it means is that we know we will get at least
5058    * window->configure_request_count more configure notifies.
5059    * We could get more configure notifies than that; some
5060    * of the configure notifies we get may be unrelated to
5061    * the configure requests. But we will get at least
5062    * window->configure_request_count notifies.
5063    */
5064
5065   if (window->configure_request_count > 0)
5066     {
5067       window->configure_request_count -= 1;
5068       gdk_window_thaw_toplevel_updates_libgtk_only (widget->window);
5069     }
5070   
5071   /* As an optimization, we avoid a resize when possible.
5072    *
5073    * The only times we can avoid a resize are:
5074    *   - we know only the position changed, not the size
5075    *   - we know we have made more requests and so will get more
5076    *     notifies and can wait to resize when we get them
5077    */
5078   
5079   if (!expected_reply &&
5080       (widget->allocation.width == event->width &&
5081        widget->allocation.height == event->height))
5082     {
5083       gdk_window_configure_finished (widget->window);
5084       return TRUE;
5085     }
5086
5087   /*
5088    * If we do need to resize, we do that by:
5089    *   - filling in widget->allocation with the new size
5090    *   - setting configure_notify_received to TRUE
5091    *     for use in gtk_window_move_resize()
5092    *   - queueing a resize, leading to invocation of
5093    *     gtk_window_move_resize() in an idle handler
5094    *
5095    */
5096   
5097   window->configure_notify_received = TRUE;
5098   
5099   widget->allocation.width = event->width;
5100   widget->allocation.height = event->height;
5101   
5102   _gtk_container_queue_resize (GTK_CONTAINER (widget));
5103   
5104   return TRUE;
5105 }
5106
5107 /* the accel_key and accel_mods fields of the key have to be setup
5108  * upon calling this function. it'll then return whether that key
5109  * is at all used as accelerator, and if so will OR in the
5110  * accel_flags member of the key.
5111  */
5112 gboolean
5113 _gtk_window_query_nonaccels (GtkWindow      *window,
5114                              guint           accel_key,
5115                              GdkModifierType accel_mods)
5116 {
5117   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5118
5119   /* movement keys are considered locked accels */
5120   if (!accel_mods)
5121     {
5122       static const guint bindings[] = {
5123         GDK_space, GDK_KP_Space, GDK_Return, GDK_ISO_Enter, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
5124         GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
5125       };
5126       guint i;
5127       
5128       for (i = 0; i < G_N_ELEMENTS (bindings); i++)
5129         if (bindings[i] == accel_key)
5130           return TRUE;
5131     }
5132
5133   /* mnemonics are considered locked accels */
5134   if (accel_mods == window->mnemonic_modifier)
5135     {
5136       GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
5137       if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
5138         return TRUE;
5139     }
5140
5141   return FALSE;
5142 }
5143
5144 /**
5145  * gtk_window_propagate_key_event:
5146  * @window:  a #GtkWindow
5147  * @event:   a #GdkEventKey
5148  *
5149  * Propagate a key press or release event to the focus widget and
5150  * up the focus container chain until a widget handles @event.
5151  * This is normally called by the default ::key_press_event and
5152  * ::key_release_event handlers for toplevel windows,
5153  * however in some cases it may be useful to call this directly when
5154  * overriding the standard key handling for a toplevel window.
5155  *
5156  * Return value: %TRUE if a widget in the focus chain handled the event.
5157  *
5158  * Since: 2.4
5159  */
5160 gboolean
5161 gtk_window_propagate_key_event (GtkWindow        *window,
5162                                 GdkEventKey      *event)
5163 {
5164   gboolean handled = FALSE;
5165   GtkWidget *widget, *focus;
5166
5167   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
5168
5169   widget = GTK_WIDGET (window);
5170   focus = window->focus_widget;
5171   if (focus)
5172     g_object_ref (focus);
5173   
5174   while (!handled &&
5175          focus && focus != widget &&
5176          gtk_widget_get_toplevel (focus) == widget)
5177     {
5178       GtkWidget *parent;
5179       
5180       if (gtk_widget_is_sensitive (focus))
5181         handled = gtk_widget_event (focus, (GdkEvent*) event);
5182       
5183       parent = focus->parent;
5184       if (parent)
5185         g_object_ref (parent);
5186       
5187       g_object_unref (focus);
5188       
5189       focus = parent;
5190     }
5191   
5192   if (focus)
5193     g_object_unref (focus);
5194
5195   return handled;
5196 }
5197
5198 static gint
5199 gtk_window_key_press_event (GtkWidget   *widget,
5200                             GdkEventKey *event)
5201 {
5202   GtkWindow *window = GTK_WINDOW (widget);
5203   gboolean handled = FALSE;
5204
5205   /* handle mnemonics and accelerators */
5206   if (!handled)
5207     handled = gtk_window_activate_key (window, event);
5208
5209   /* handle focus widget key events */
5210   if (!handled)
5211     handled = gtk_window_propagate_key_event (window, event);
5212
5213   /* Chain up, invokes binding set */
5214   if (!handled)
5215     handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_press_event (widget, event);
5216
5217   return handled;
5218 }
5219
5220 static gint
5221 gtk_window_key_release_event (GtkWidget   *widget,
5222                               GdkEventKey *event)
5223 {
5224   GtkWindow *window = GTK_WINDOW (widget);
5225   gboolean handled = FALSE;
5226
5227   /* handle focus widget key events */
5228   if (!handled)
5229     handled = gtk_window_propagate_key_event (window, event);
5230
5231   /* Chain up, invokes binding set */
5232   if (!handled)
5233     handled = GTK_WIDGET_CLASS (gtk_window_parent_class)->key_release_event (widget, event);
5234
5235   return handled;
5236 }
5237
5238 static void
5239 gtk_window_real_activate_default (GtkWindow *window)
5240 {
5241   gtk_window_activate_default (window);
5242 }
5243
5244 static void
5245 gtk_window_real_activate_focus (GtkWindow *window)
5246 {
5247   gtk_window_activate_focus (window);
5248 }
5249
5250 static void
5251 gtk_window_move_focus (GtkWindow       *window,
5252                        GtkDirectionType dir)
5253 {
5254   gtk_widget_child_focus (GTK_WIDGET (window), dir);
5255   
5256   if (!GTK_CONTAINER (window)->focus_child)
5257     gtk_window_set_focus (window, NULL);
5258 }
5259
5260 static gint
5261 gtk_window_enter_notify_event (GtkWidget        *widget,
5262                                GdkEventCrossing *event)
5263 {
5264   return FALSE;
5265 }
5266
5267 static gint
5268 gtk_window_leave_notify_event (GtkWidget        *widget,
5269                                GdkEventCrossing *event)
5270 {
5271   return FALSE;
5272 }
5273
5274 static void
5275 do_focus_change (GtkWidget *widget,
5276                  gboolean   in)
5277 {
5278   GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
5279   
5280   g_object_ref (widget);
5281   
5282   if (in)
5283     GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
5284   else
5285     GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
5286   
5287   fevent->focus_change.type = GDK_FOCUS_CHANGE;
5288   fevent->focus_change.window = widget->window;
5289   if (widget->window)
5290     g_object_ref (widget->window);
5291   fevent->focus_change.in = in;
5292   
5293   gtk_widget_event (widget, fevent);
5294   
5295   g_object_notify (G_OBJECT (widget), "has-focus");
5296
5297   g_object_unref (widget);
5298   gdk_event_free (fevent);
5299 }
5300
5301 static gint
5302 gtk_window_focus_in_event (GtkWidget     *widget,
5303                            GdkEventFocus *event)
5304 {
5305   GtkWindow *window = GTK_WINDOW (widget);
5306
5307   /* It appears spurious focus in events can occur when
5308    *  the window is hidden. So we'll just check to see if
5309    *  the window is visible before actually handling the
5310    *  event
5311    */
5312   if (gtk_widget_get_visible (widget))
5313     {
5314       _gtk_window_set_has_toplevel_focus (window, TRUE);
5315       _gtk_window_set_is_active (window, TRUE);
5316     }
5317       
5318   return FALSE;
5319 }
5320
5321 static gint
5322 gtk_window_focus_out_event (GtkWidget     *widget,
5323                             GdkEventFocus *event)
5324 {
5325   GtkWindow *window = GTK_WINDOW (widget);
5326   gboolean auto_mnemonics;
5327
5328   _gtk_window_set_has_toplevel_focus (window, FALSE);
5329   _gtk_window_set_is_active (window, FALSE);
5330
5331   /* set the mnemonic-visible property to false */
5332   g_object_get (gtk_widget_get_settings (widget),
5333                 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
5334   if (auto_mnemonics)
5335     gtk_window_set_mnemonics_visible (window, FALSE);
5336
5337   return FALSE;
5338 }
5339
5340 static GdkAtom atom_rcfiles = GDK_NONE;
5341 static GdkAtom atom_iconthemes = GDK_NONE;
5342
5343 static void
5344 send_client_message_to_embedded_windows (GtkWidget *widget,
5345                                          GdkAtom    message_type)
5346 {
5347   GList *embedded_windows;
5348
5349   embedded_windows = g_object_get_qdata (G_OBJECT (widget), quark_gtk_embedded);
5350   if (embedded_windows)
5351     {
5352       GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
5353       int i;
5354       
5355       for (i = 0; i < 5; i++)
5356         send_event->client.data.l[i] = 0;
5357       send_event->client.data_format = 32;
5358       send_event->client.message_type = message_type;
5359       
5360       while (embedded_windows)
5361         {
5362           GdkNativeWindow xid = GDK_GPOINTER_TO_NATIVE_WINDOW(embedded_windows->data);
5363           gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
5364           embedded_windows = embedded_windows->next;
5365         }
5366
5367       gdk_event_free (send_event);
5368     }
5369 }
5370
5371 static gint
5372 gtk_window_client_event (GtkWidget      *widget,
5373                          GdkEventClient *event)
5374 {
5375   if (!atom_rcfiles)
5376     {
5377       atom_rcfiles = gdk_atom_intern_static_string ("_GTK_READ_RCFILES");
5378       atom_iconthemes = gdk_atom_intern_static_string ("_GTK_LOAD_ICONTHEMES");
5379     }
5380
5381   if (event->message_type == atom_rcfiles) 
5382     {
5383       send_client_message_to_embedded_windows (widget, atom_rcfiles);
5384       gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
5385     }
5386
5387   if (event->message_type == atom_iconthemes) 
5388     {
5389       send_client_message_to_embedded_windows (widget, atom_iconthemes);
5390       _gtk_icon_theme_check_reload (gtk_widget_get_display (widget));    
5391     }
5392
5393   return FALSE;
5394 }
5395
5396 static void
5397 gtk_window_check_resize (GtkContainer *container)
5398 {
5399   if (gtk_widget_get_visible (GTK_WIDGET (container)))
5400     gtk_window_move_resize (GTK_WINDOW (container));
5401 }
5402
5403 static gboolean
5404 gtk_window_focus (GtkWidget        *widget,
5405                   GtkDirectionType  direction)
5406 {
5407   GtkBin *bin;
5408   GtkWindow *window;
5409   GtkContainer *container;
5410   GtkWidget *old_focus_child;
5411   GtkWidget *parent;
5412
5413   container = GTK_CONTAINER (widget);
5414   window = GTK_WINDOW (widget);
5415   bin = GTK_BIN (widget);
5416
5417   old_focus_child = container->focus_child;
5418   
5419   /* We need a special implementation here to deal properly with wrapping
5420    * around in the tab chain without the danger of going into an
5421    * infinite loop.
5422    */
5423   if (old_focus_child)
5424     {
5425       if (gtk_widget_child_focus (old_focus_child, direction))
5426         return TRUE;
5427     }
5428
5429   if (window->focus_widget)
5430     {
5431       if (direction == GTK_DIR_LEFT ||
5432           direction == GTK_DIR_RIGHT ||
5433           direction == GTK_DIR_UP ||
5434           direction == GTK_DIR_DOWN)
5435         {
5436           return FALSE;
5437         }
5438       
5439       /* Wrapped off the end, clear the focus setting for the toplpevel */
5440       parent = window->focus_widget->parent;
5441       while (parent)
5442         {
5443           gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
5444           parent = GTK_WIDGET (parent)->parent;
5445         }
5446       
5447       gtk_window_set_focus (GTK_WINDOW (container), NULL);
5448     }
5449
5450   /* Now try to focus the first widget in the window */
5451   if (bin->child)
5452     {
5453       if (gtk_widget_child_focus (bin->child, direction))
5454         return TRUE;
5455     }
5456
5457   return FALSE;
5458 }
5459
5460 static void
5461 gtk_window_real_set_focus (GtkWindow *window,
5462                            GtkWidget *focus)
5463 {
5464   GtkWidget *old_focus = window->focus_widget;
5465   gboolean had_default = FALSE;
5466   gboolean focus_had_default = FALSE;
5467   gboolean old_focus_had_default = FALSE;
5468
5469   if (old_focus)
5470     {
5471       g_object_ref (old_focus);
5472       g_object_freeze_notify (G_OBJECT (old_focus));
5473       old_focus_had_default = gtk_widget_has_default (old_focus);
5474     }
5475   if (focus)
5476     {
5477       g_object_ref (focus);
5478       g_object_freeze_notify (G_OBJECT (focus));
5479       focus_had_default = gtk_widget_has_default (focus);
5480     }
5481   
5482   if (window->default_widget)
5483     had_default = gtk_widget_has_default (window->default_widget);
5484   
5485   if (window->focus_widget)
5486     {
5487       if (gtk_widget_get_receives_default (window->focus_widget) &&
5488           (window->focus_widget != window->default_widget))
5489         {
5490           GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
5491           gtk_widget_queue_draw (window->focus_widget);
5492           
5493           if (window->default_widget)
5494             GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
5495         }
5496
5497       window->focus_widget = NULL;
5498
5499       if (window->has_focus)
5500         do_focus_change (old_focus, FALSE);
5501
5502       g_object_notify (G_OBJECT (old_focus), "is-focus");
5503     }
5504
5505   /* The above notifications may have set a new focus widget,
5506    * if so, we don't want to override it.
5507    */
5508   if (focus && !window->focus_widget)
5509     {
5510       window->focus_widget = focus;
5511   
5512       if (gtk_widget_get_receives_default (window->focus_widget) &&
5513           (window->focus_widget != window->default_widget))
5514         {
5515           if (gtk_widget_get_can_default (window->focus_widget))
5516             GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
5517
5518           if (window->default_widget)
5519             GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
5520         }
5521
5522       if (window->has_focus)
5523         do_focus_change (window->focus_widget, TRUE);
5524
5525       g_object_notify (G_OBJECT (window->focus_widget), "is-focus");
5526     }
5527
5528   /* If the default widget changed, a redraw will have been queued
5529    * on the old and new default widgets by gtk_window_set_default(), so
5530    * we only have to worry about the case where it didn't change.
5531    * We'll sometimes queue a draw twice on the new widget but that
5532    * is harmless.
5533    */
5534   if (window->default_widget &&
5535       (had_default != gtk_widget_has_default (window->default_widget)))
5536     gtk_widget_queue_draw (window->default_widget);
5537   
5538   if (old_focus)
5539     {
5540       if (old_focus_had_default != gtk_widget_has_default (old_focus))
5541         gtk_widget_queue_draw (old_focus);
5542         
5543       g_object_thaw_notify (G_OBJECT (old_focus));
5544       g_object_unref (old_focus);
5545     }
5546   if (focus)
5547     {
5548       if (focus_had_default != gtk_widget_has_default (focus))
5549         gtk_widget_queue_draw (focus);
5550
5551       g_object_thaw_notify (G_OBJECT (focus));
5552       g_object_unref (focus);
5553     }
5554 }
5555
5556 /**
5557  * _gtk_window_unset_focus_and_default:
5558  * @window: a #GtkWindow
5559  * @widget: a widget inside of @window
5560  * 
5561  * Checks whether the focus and default widgets of @window are
5562  * @widget or a descendent of @widget, and if so, unset them.
5563  **/
5564 void
5565 _gtk_window_unset_focus_and_default (GtkWindow *window,
5566                                      GtkWidget *widget)
5567
5568 {
5569   GtkWidget *child;
5570
5571   g_object_ref (window);
5572   g_object_ref (widget);
5573       
5574   if (GTK_CONTAINER (widget->parent)->focus_child == widget)
5575     {
5576       child = window->focus_widget;
5577       
5578       while (child && child != widget)
5579         child = child->parent;
5580   
5581       if (child == widget)
5582         gtk_window_set_focus (GTK_WINDOW (window), NULL);
5583     }
5584       
5585   child = window->default_widget;
5586       
5587   while (child && child != widget)
5588     child = child->parent;
5589       
5590   if (child == widget)
5591     gtk_window_set_default (window, NULL);
5592   
5593   g_object_unref (widget);
5594   g_object_unref (window);
5595 }
5596
5597 /*********************************
5598  * Functions related to resizing *
5599  *********************************/
5600
5601 /* This function doesn't constrain to geometry hints */
5602 static void 
5603 gtk_window_compute_configure_request_size (GtkWindow *window,
5604                                            guint     *width,
5605                                            guint     *height)
5606 {
5607   GtkRequisition requisition;
5608   GtkWindowGeometryInfo *info;
5609   GtkWidget *widget;
5610
5611   /* Preconditions:
5612    *  - we've done a size request
5613    */
5614   
5615   widget = GTK_WIDGET (window);
5616
5617   info = gtk_window_get_geometry_info (window, FALSE);
5618   
5619   if (window->need_default_size)
5620     {
5621       gtk_widget_get_child_requisition (widget, &requisition);
5622
5623       /* Default to requisition */
5624       *width = requisition.width;
5625       *height = requisition.height;
5626
5627       /* If window is empty so requests 0, default to random nonzero size */
5628        if (*width == 0 && *height == 0)
5629          {
5630            *width = 200;
5631            *height = 200;
5632          }
5633
5634        /* Override requisition with default size */
5635
5636        if (info)
5637          {
5638            gint base_width = 0;
5639            gint base_height = 0;
5640            gint min_width = 0;
5641            gint min_height = 0;
5642            gint width_inc = 1;
5643            gint height_inc = 1;
5644            
5645            if (info->default_is_geometry &&
5646                (info->default_width > 0 || info->default_height > 0))
5647              {
5648                GdkGeometry geometry;
5649                guint flags;
5650                
5651                gtk_window_compute_hints (window, &geometry, &flags);
5652
5653                if (flags & GDK_HINT_BASE_SIZE)
5654                  {
5655                    base_width = geometry.base_width;
5656                    base_height = geometry.base_height;
5657                  }
5658                if (flags & GDK_HINT_MIN_SIZE)
5659                  {
5660                    min_width = geometry.min_width;
5661                    min_height = geometry.min_height;
5662                  }
5663                if (flags & GDK_HINT_RESIZE_INC)
5664                  {
5665                    width_inc = geometry.width_inc;
5666                    height_inc = geometry.height_inc;
5667                  }
5668              }
5669              
5670            if (info->default_width > 0)
5671              *width = MAX (info->default_width * width_inc + base_width, min_width);
5672            
5673            if (info->default_height > 0)
5674              *height = MAX (info->default_height * height_inc + base_height, min_height);
5675          }
5676     }
5677   else
5678     {
5679       /* Default to keeping current size */
5680       *width = widget->allocation.width;
5681       *height = widget->allocation.height;
5682     }
5683
5684   /* Override any size with gtk_window_resize() values */
5685   if (info)
5686     {
5687       if (info->resize_width > 0)
5688         *width = info->resize_width;
5689
5690       if (info->resize_height > 0)
5691         *height = info->resize_height;
5692     }
5693
5694   /* Don't ever request zero width or height, its not supported by
5695      gdk. The size allocation code will round it to 1 anyway but if
5696      we do it then the value returned from this function will is
5697      not comparable to the size allocation read from the GtkWindow. */
5698   *width = MAX (*width, 1);
5699   *height = MAX (*height, 1);
5700 }
5701
5702 static GtkWindowPosition
5703 get_effective_position (GtkWindow *window)
5704 {
5705   GtkWindowPosition pos = window->position;
5706
5707   if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
5708       (window->transient_parent == NULL ||
5709        !gtk_widget_get_mapped (GTK_WIDGET (window->transient_parent))))
5710     pos = GTK_WIN_POS_NONE;
5711
5712   return pos;
5713 }
5714
5715 static int
5716 get_center_monitor_of_window (GtkWindow *window)
5717 {
5718   /* We could try to sort out the relative positions of the monitors and
5719    * stuff, or we could just be losers and assume you have a row
5720    * or column of monitors.
5721    */
5722   return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
5723 }
5724
5725 static int
5726 get_monitor_containing_pointer (GtkWindow *window)
5727 {
5728   gint px, py;
5729   gint monitor_num;
5730   GdkScreen *window_screen;
5731   GdkScreen *pointer_screen;
5732
5733   window_screen = gtk_window_check_screen (window);
5734   gdk_display_get_pointer (gdk_screen_get_display (window_screen),
5735                            &pointer_screen,
5736                            &px, &py, NULL);
5737
5738   if (pointer_screen == window_screen)
5739     monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
5740   else
5741     monitor_num = -1;
5742
5743   return monitor_num;
5744 }
5745
5746 static void
5747 center_window_on_monitor (GtkWindow *window,
5748                           gint       w,
5749                           gint       h,
5750                           gint      *x,
5751                           gint      *y)
5752 {
5753   GdkRectangle monitor;
5754   int monitor_num;
5755
5756   monitor_num = get_monitor_containing_pointer (window);
5757   
5758   if (monitor_num == -1)
5759     monitor_num = get_center_monitor_of_window (window);
5760
5761   gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
5762                                    monitor_num, &monitor);
5763   
5764   *x = (monitor.width - w) / 2 + monitor.x;
5765   *y = (monitor.height - h) / 2 + monitor.y;
5766
5767   /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
5768    * and WM decorations.
5769    */
5770   if (*x < monitor.x)
5771     *x = monitor.x;
5772   if (*y < monitor.y)
5773     *y = monitor.y;
5774 }
5775
5776 static void
5777 clamp (gint *base,
5778        gint  extent,
5779        gint  clamp_base,
5780        gint  clamp_extent)
5781 {
5782   if (extent > clamp_extent)
5783     /* Center */
5784     *base = clamp_base + clamp_extent/2 - extent/2;
5785   else if (*base < clamp_base)
5786     *base = clamp_base;
5787   else if (*base + extent > clamp_base + clamp_extent)
5788     *base = clamp_base + clamp_extent - extent;
5789 }
5790
5791 static void
5792 clamp_window_to_rectangle (gint               *x,
5793                            gint               *y,
5794                            gint                w,
5795                            gint                h,
5796                            const GdkRectangle *rect)
5797 {
5798 #ifdef DEBUGGING_OUTPUT
5799   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);
5800 #endif
5801
5802   /* If it is too large, center it. If it fits on the monitor but is
5803    * partially outside, move it to the closest edge. Do this
5804    * separately in x and y directions.
5805    */
5806   clamp (x, w, rect->x, rect->width);
5807   clamp (y, h, rect->y, rect->height);
5808 #ifdef DEBUGGING_OUTPUT
5809   g_print (" ==> %+d%+d: %dx%d\n", *x, *y, w, h);
5810 #endif
5811 }
5812
5813
5814 static void
5815 gtk_window_compute_configure_request (GtkWindow    *window,
5816                                       GdkRectangle *request,
5817                                       GdkGeometry  *geometry,
5818                                       guint        *flags)
5819 {
5820   GdkGeometry new_geometry;
5821   guint new_flags;
5822   int w, h;
5823   GtkWidget *widget;
5824   GtkWindowPosition pos;
5825   GtkWidget *parent_widget;
5826   GtkWindowGeometryInfo *info;
5827   GdkScreen *screen;
5828   int x, y;
5829   
5830   widget = GTK_WIDGET (window);
5831
5832   screen = gtk_window_check_screen (window);
5833   
5834   gtk_widget_size_request (widget, NULL);
5835   gtk_window_compute_configure_request_size (window, (guint *)&w, (guint *)&h);
5836   
5837   gtk_window_compute_hints (window, &new_geometry, &new_flags);
5838   gtk_window_constrain_size (window,
5839                              &new_geometry, new_flags,
5840                              w, h,
5841                              &w, &h);
5842
5843   parent_widget = (GtkWidget*) window->transient_parent;
5844   
5845   pos = get_effective_position (window);
5846   info = gtk_window_get_geometry_info (window, FALSE);
5847   
5848   /* by default, don't change position requested */
5849   if (info)
5850     {
5851       x = info->last.configure_request.x;
5852       y = info->last.configure_request.y;
5853     }
5854   else
5855     {
5856       x = 0;
5857       y = 0;
5858     }
5859
5860
5861   if (window->need_default_position)
5862     {
5863
5864       /* FIXME this all interrelates with window gravity.
5865        * For most of them I think we want to set GRAVITY_CENTER.
5866        *
5867        * Not sure how to go about that.
5868        */
5869       
5870       switch (pos)
5871         {
5872           /* here we are only handling CENTER_ALWAYS
5873            * as it relates to default positioning,
5874            * where it's equivalent to simply CENTER
5875            */
5876         case GTK_WIN_POS_CENTER_ALWAYS:
5877         case GTK_WIN_POS_CENTER:
5878           center_window_on_monitor (window, w, h, &x, &y);
5879           break;
5880       
5881         case GTK_WIN_POS_CENTER_ON_PARENT:
5882           {
5883             gint monitor_num;
5884             GdkRectangle monitor;
5885             gint ox, oy;
5886             
5887             g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */
5888
5889             if (parent_widget->window != NULL)
5890               monitor_num = gdk_screen_get_monitor_at_window (screen,
5891                                                               parent_widget->window);
5892             else
5893               monitor_num = -1;
5894             
5895             gdk_window_get_origin (parent_widget->window,
5896                                    &ox, &oy);
5897             
5898             x = ox + (parent_widget->allocation.width - w) / 2;
5899             y = oy + (parent_widget->allocation.height - h) / 2;
5900             
5901             /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
5902              * WM decorations. If parent wasn't on a monitor, just
5903              * give up.
5904              */
5905             if (monitor_num >= 0)
5906               {
5907                 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
5908                 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
5909               }
5910           }
5911           break;
5912
5913         case GTK_WIN_POS_MOUSE:
5914           {
5915             gint screen_width = gdk_screen_get_width (screen);
5916             gint screen_height = gdk_screen_get_height (screen);
5917             gint monitor_num;
5918             GdkRectangle monitor;
5919             GdkScreen *pointer_screen;
5920             gint px, py;
5921             
5922             gdk_display_get_pointer (gdk_screen_get_display (screen),
5923                                      &pointer_screen,
5924                                      &px, &py, NULL);
5925
5926             if (pointer_screen == screen)
5927               monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
5928             else
5929               monitor_num = -1;
5930             
5931             x = px - w / 2;
5932             y = py - h / 2;
5933             x = CLAMP (x, 0, screen_width - w);
5934             y = CLAMP (y, 0, screen_height - h);
5935
5936             /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
5937              * WM decorations. Don't try to figure out what's going
5938              * on if the mouse wasn't inside a monitor.
5939              */
5940             if (monitor_num >= 0)
5941               {
5942                 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
5943                 clamp_window_to_rectangle (&x, &y, w, h, &monitor);
5944               }
5945           }
5946           break;
5947
5948         default:
5949           break;
5950         }
5951     } /* if (window->need_default_position) */
5952
5953   if (window->need_default_position && info &&
5954       info->initial_pos_set)
5955     {
5956       x = info->initial_x;
5957       y = info->initial_y;
5958       gtk_window_constrain_position (window, w, h, &x, &y);
5959     }
5960   
5961   request->x = x;
5962   request->y = y;
5963   request->width = w;
5964   request->height = h;
5965
5966   if (geometry)
5967     *geometry = new_geometry;
5968   if (flags)
5969     *flags = new_flags;
5970 }
5971
5972 static void
5973 gtk_window_constrain_position (GtkWindow    *window,
5974                                gint          new_width,
5975                                gint          new_height,
5976                                gint         *x,
5977                                gint         *y)
5978 {
5979   /* See long comments in gtk_window_move_resize()
5980    * on when it's safe to call this function.
5981    */
5982   if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
5983     {
5984       gint center_x, center_y;
5985
5986       center_window_on_monitor (window, new_width, new_height, &center_x, &center_y);
5987       
5988       *x = center_x;
5989       *y = center_y;
5990     }
5991 }
5992
5993 static void
5994 gtk_window_move_resize (GtkWindow *window)
5995 {
5996   /* Overview:
5997    *
5998    * First we determine whether any information has changed that would
5999    * cause us to revise our last configure request.  If we would send
6000    * a different configure request from last time, then
6001    * configure_request_size_changed = TRUE or
6002    * configure_request_pos_changed = TRUE. configure_request_size_changed
6003    * may be true due to new hints, a gtk_window_resize(), or whatever.
6004    * configure_request_pos_changed may be true due to gtk_window_set_position()
6005    * or gtk_window_move().
6006    *
6007    * If the configure request has changed, we send off a new one.  To
6008    * ensure GTK+ invariants are maintained (resize queue does what it
6009    * should), we go ahead and size_allocate the requested size in this
6010    * function.
6011    *
6012    * If the configure request has not changed, we don't ever resend
6013    * it, because it could mean fighting the user or window manager.
6014    *
6015    * 
6016    *   To prepare the configure request, we come up with a base size/pos:
6017    *      - the one from gtk_window_move()/gtk_window_resize()
6018    *      - else default_width, default_height if we haven't ever
6019    *        been mapped
6020    *      - else the size request if we haven't ever been mapped,
6021    *        as a substitute default size
6022    *      - else the current size of the window, as received from
6023    *        configure notifies (i.e. the current allocation)
6024    *
6025    *   If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain
6026    *   the position request to be centered.
6027    */
6028   GtkWidget *widget;
6029   GtkContainer *container;
6030   GtkWindowGeometryInfo *info;
6031   GdkGeometry new_geometry;
6032   guint new_flags;
6033   GdkRectangle new_request;
6034   gboolean configure_request_size_changed;
6035   gboolean configure_request_pos_changed;
6036   gboolean hints_changed; /* do we need to send these again */
6037   GtkWindowLastGeometryInfo saved_last_info;
6038   
6039   widget = GTK_WIDGET (window);
6040   container = GTK_CONTAINER (widget);
6041   info = gtk_window_get_geometry_info (window, TRUE);
6042   
6043   configure_request_size_changed = FALSE;
6044   configure_request_pos_changed = FALSE;
6045   
6046   gtk_window_compute_configure_request (window, &new_request,
6047                                         &new_geometry, &new_flags);  
6048   
6049   /* This check implies the invariant that we never set info->last
6050    * without setting the hints and sending off a configure request.
6051    *
6052    * If we change info->last without sending the request, we may
6053    * miss a request.
6054    */
6055   if (info->last.configure_request.x != new_request.x ||
6056       info->last.configure_request.y != new_request.y)
6057     configure_request_pos_changed = TRUE;
6058
6059   if ((info->last.configure_request.width != new_request.width ||
6060        info->last.configure_request.height != new_request.height))
6061     configure_request_size_changed = TRUE;
6062   
6063   hints_changed = FALSE;
6064   
6065   if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
6066                                  &new_geometry, new_flags))
6067     {
6068       hints_changed = TRUE;
6069     }
6070   
6071   /* Position Constraints
6072    * ====================
6073    * 
6074    * POS_CENTER_ALWAYS is conceptually a constraint rather than
6075    * a default. The other POS_ values are used only when the
6076    * window is shown, not after that.
6077    * 
6078    * However, we can't implement a position constraint as
6079    * "anytime the window size changes, center the window"
6080    * because this may well end up fighting the WM or user.  In
6081    * fact it gets in an infinite loop with at least one WM.
6082    *
6083    * Basically, applications are in no way in a position to
6084    * constrain the position of a window, with one exception:
6085    * override redirect windows. (Really the intended purpose
6086    * of CENTER_ALWAYS anyhow, I would think.)
6087    *
6088    * So the way we implement this "constraint" is to say that when WE
6089    * cause a move or resize, i.e. we make a configure request changing
6090    * window size, we recompute the CENTER_ALWAYS position to reflect
6091    * the new window size, and include it in our request.  Also, if we
6092    * just turned on CENTER_ALWAYS we snap to center with a new
6093    * request.  Otherwise, if we are just NOTIFIED of a move or resize
6094    * done by someone else e.g. the window manager, we do NOT send a
6095    * new configure request.
6096    *
6097    * For override redirect windows, this works fine; all window
6098    * sizes are from our configure requests. For managed windows,
6099    * it is at least semi-sane, though who knows what the
6100    * app author is thinking.
6101    */
6102
6103   /* This condition should be kept in sync with the condition later on
6104    * that determines whether we send a configure request.  i.e. we
6105    * should do this position constraining anytime we were going to
6106    * send a configure request anyhow, plus when constraints have
6107    * changed.
6108    */
6109   if (configure_request_pos_changed ||
6110       configure_request_size_changed ||
6111       hints_changed ||
6112       info->position_constraints_changed)
6113     {
6114       /* We request the constrained position if:
6115        *  - we were changing position, and need to clamp
6116        *    the change to the constraint
6117        *  - we're changing the size anyway
6118        *  - set_position() was called to toggle CENTER_ALWAYS on
6119        */
6120
6121       gtk_window_constrain_position (window,
6122                                      new_request.width,
6123                                      new_request.height,
6124                                      &new_request.x,
6125                                      &new_request.y);
6126       
6127       /* Update whether we need to request a move */
6128       if (info->last.configure_request.x != new_request.x ||
6129           info->last.configure_request.y != new_request.y)
6130         configure_request_pos_changed = TRUE;
6131       else
6132         configure_request_pos_changed = FALSE;
6133     }
6134
6135 #if 0
6136   if (window->type == GTK_WINDOW_TOPLEVEL)
6137     {
6138       int notify_x, notify_y;
6139
6140       /* this is the position from the last configure notify */
6141       gdk_window_get_position (widget->window, &notify_x, &notify_y);
6142     
6143       g_message ("--- %s ---\n"
6144                  "last  : %d,%d\t%d x %d\n"
6145                  "this  : %d,%d\t%d x %d\n"
6146                  "alloc : %d,%d\t%d x %d\n"
6147                  "req   :      \t%d x %d\n"
6148                  "resize:      \t%d x %d\n" 
6149                  "size_changed: %d pos_changed: %d hints_changed: %d\n"
6150                  "configure_notify_received: %d\n"
6151                  "configure_request_count: %d\n"
6152                  "position_constraints_changed: %d\n",
6153                  window->title ? window->title : "(no title)",
6154                  info->last.configure_request.x,
6155                  info->last.configure_request.y,
6156                  info->last.configure_request.width,
6157                  info->last.configure_request.height,
6158                  new_request.x,
6159                  new_request.y,
6160                  new_request.width,
6161                  new_request.height,
6162                  notify_x, notify_y,
6163                  widget->allocation.width,
6164                  widget->allocation.height,
6165                  widget->requisition.width,
6166                  widget->requisition.height,
6167                  info->resize_width,
6168                  info->resize_height,
6169                  configure_request_pos_changed,
6170                  configure_request_size_changed,
6171                  hints_changed,
6172                  window->configure_notify_received,
6173                  window->configure_request_count,
6174                  info->position_constraints_changed);
6175     }
6176 #endif
6177   
6178   saved_last_info = info->last;
6179   info->last.geometry = new_geometry;
6180   info->last.flags = new_flags;
6181   info->last.configure_request = new_request;
6182   
6183   /* need to set PPosition so the WM will look at our position,
6184    * but we don't want to count PPosition coming and going as a hints
6185    * change for future iterations. So we saved info->last prior to
6186    * this.
6187    */
6188   
6189   /* Also, if the initial position was explicitly set, then we always
6190    * toggle on PPosition. This makes gtk_window_move(window, 0, 0)
6191    * work.
6192    */
6193
6194   /* Also, we toggle on PPosition if GTK_WIN_POS_ is in use and
6195    * this is an initial map
6196    */
6197   
6198   if ((configure_request_pos_changed ||
6199        info->initial_pos_set ||
6200        (window->need_default_position &&
6201         get_effective_position (window) != GTK_WIN_POS_NONE)) &&
6202       (new_flags & GDK_HINT_POS) == 0)
6203     {
6204       new_flags |= GDK_HINT_POS;
6205       hints_changed = TRUE;
6206     }
6207   
6208   /* Set hints if necessary
6209    */
6210   if (hints_changed)
6211     gdk_window_set_geometry_hints (widget->window,
6212                                    &new_geometry,
6213                                    new_flags);
6214   
6215   /* handle resizing/moving and widget tree allocation
6216    */
6217   if (window->configure_notify_received)
6218     { 
6219       GtkAllocation allocation;
6220
6221       /* If we have received a configure event since
6222        * the last time in this function, we need to
6223        * accept our new size and size_allocate child widgets.
6224        * (see gtk_window_configure_event() for more details).
6225        *
6226        * 1 or more configure notifies may have been received.
6227        * Also, configure_notify_received will only be TRUE
6228        * if all expected configure notifies have been received
6229        * (one per configure request), as an optimization.
6230        *
6231        */
6232       window->configure_notify_received = FALSE;
6233
6234       /* gtk_window_configure_event() filled in widget->allocation */
6235       allocation = widget->allocation;
6236       gtk_widget_size_allocate (widget, &allocation);
6237
6238       gdk_window_process_updates (widget->window, TRUE);
6239       
6240       gdk_window_configure_finished (widget->window);
6241
6242       /* If the configure request changed, it means that
6243        * we either:
6244        *   1) coincidentally changed hints or widget properties
6245        *      impacting the configure request before getting
6246        *      a configure notify, or
6247        *   2) some broken widget is changing its size request
6248        *      during size allocation, resulting in
6249        *      a false appearance of changed configure request.
6250        *
6251        * For 1), we could just go ahead and ask for the
6252        * new size right now, but doing that for 2)
6253        * might well be fighting the user (and can even
6254        * trigger a loop). Since we really don't want to
6255        * do that, we requeue a resize in hopes that
6256        * by the time it gets handled, the child has seen
6257        * the light and is willing to go along with the
6258        * new size. (this happens for the zvt widget, since
6259        * the size_allocate() above will have stored the
6260        * requisition corresponding to the new size in the
6261        * zvt widget)
6262        *
6263        * This doesn't buy us anything for 1), but it shouldn't
6264        * hurt us too badly, since it is what would have
6265        * happened if we had gotten the configure event before
6266        * the new size had been set.
6267        */
6268
6269       if (configure_request_size_changed ||
6270           configure_request_pos_changed)
6271         {
6272           /* Don't change the recorded last info after all, because we
6273            * haven't actually updated to the new info yet - we decided
6274            * to postpone our configure request until later.
6275            */
6276           info->last = saved_last_info;
6277           
6278           gtk_widget_queue_resize_no_redraw (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
6279         }
6280
6281       return;                   /* Bail out, we didn't really process the move/resize */
6282     }
6283   else if ((configure_request_size_changed || hints_changed) &&
6284            (widget->allocation.width != new_request.width ||
6285             widget->allocation.height != new_request.height))
6286
6287     {
6288       /* We are in one of the following situations:
6289        * A. configure_request_size_changed
6290        *    our requisition has changed and we need a different window size,
6291        *    so we request it from the window manager.
6292        * B. !configure_request_size_changed && hints_changed
6293        *    the window manager rejects our size, but we have just changed the
6294        *    window manager hints, so there's a chance our request will
6295        *    be honoured this time, so we try again.
6296        *
6297        * However, if the new requisition is the same as the current allocation,
6298        * we don't request it again, since we won't get a ConfigureNotify back from
6299        * the window manager unless it decides to change our requisition. If
6300        * we don't get the ConfigureNotify back, the resize queue will never be run.
6301        */
6302
6303       /* Now send the configure request */
6304       if (configure_request_pos_changed)
6305         {
6306           if (window->frame)
6307             {
6308               gdk_window_move_resize (window->frame,
6309                                       new_request.x - window->frame_left,
6310                                       new_request.y - window->frame_top,
6311                                       new_request.width + window->frame_left + window->frame_right,
6312                                       new_request.height + window->frame_top + window->frame_bottom);
6313               gdk_window_resize (widget->window,
6314                                  new_request.width, new_request.height);
6315             }
6316           else
6317             gdk_window_move_resize (widget->window,
6318                                     new_request.x, new_request.y,
6319                                     new_request.width, new_request.height);
6320         }
6321       else  /* only size changed */
6322         {
6323           if (window->frame)
6324             gdk_window_resize (window->frame,
6325                                new_request.width + window->frame_left + window->frame_right,
6326                                new_request.height + window->frame_top + window->frame_bottom);
6327           gdk_window_resize (widget->window,
6328                              new_request.width, new_request.height);
6329         }
6330       
6331       if (window->type == GTK_WINDOW_POPUP)
6332         {
6333           GtkAllocation allocation;
6334
6335           /* Directly size allocate for override redirect (popup) windows. */
6336           allocation.x = 0;
6337           allocation.y = 0;
6338           allocation.width = new_request.width;
6339           allocation.height = new_request.height;
6340
6341           gtk_widget_size_allocate (widget, &allocation);
6342
6343           gdk_window_process_updates (widget->window, TRUE);
6344
6345           if (container->resize_mode == GTK_RESIZE_QUEUE)
6346             gtk_widget_queue_draw (widget);
6347         }
6348       else
6349         {
6350           /* Increment the number of have-not-yet-received-notify requests */
6351           window->configure_request_count += 1;
6352           gdk_window_freeze_toplevel_updates_libgtk_only (widget->window);
6353
6354           /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
6355            * configure event in response to our resizing request.
6356            * the configure event will cause a new resize with
6357            * ->configure_notify_received=TRUE.
6358            * until then, we want to
6359            * - discard expose events
6360            * - coalesce resizes for our children
6361            * - defer any window resizes until the configure event arrived
6362            * to achieve this, we queue a resize for the window, but remove its
6363            * resizing handler, so resizing will not be handled from the next
6364            * idle handler but when the configure event arrives.
6365            *
6366            * FIXME: we should also dequeue the pending redraws here, since
6367            * we handle those ourselves upon ->configure_notify_received==TRUE.
6368            */
6369           if (container->resize_mode == GTK_RESIZE_QUEUE)
6370             {
6371               gtk_widget_queue_resize_no_redraw (widget);
6372               _gtk_container_dequeue_resize_handler (container);
6373             }
6374         }
6375     }
6376   else
6377     {
6378       /* Handle any position changes.
6379        */
6380       if (configure_request_pos_changed)
6381         {
6382           if (window->frame)
6383             {
6384               gdk_window_move (window->frame,
6385                                new_request.x - window->frame_left,
6386                                new_request.y - window->frame_top);
6387             }
6388           else
6389             gdk_window_move (widget->window,
6390                              new_request.x, new_request.y);
6391         }
6392
6393       /* And run the resize queue.
6394        */
6395       gtk_container_resize_children (container);
6396     }
6397   
6398   /* We have now processed a move/resize since the last position
6399    * constraint change, setting of the initial position, or resize.
6400    * (Not resetting these flags here can lead to infinite loops for
6401    * GTK_RESIZE_IMMEDIATE containers)
6402    */
6403   info->position_constraints_changed = FALSE;
6404   info->initial_pos_set = FALSE;
6405   info->resize_width = -1;
6406   info->resize_height = -1;
6407 }
6408
6409 /* Compare two sets of Geometry hints for equality.
6410  */
6411 static gboolean
6412 gtk_window_compare_hints (GdkGeometry *geometry_a,
6413                           guint        flags_a,
6414                           GdkGeometry *geometry_b,
6415                           guint        flags_b)
6416 {
6417   if (flags_a != flags_b)
6418     return FALSE;
6419   
6420   if ((flags_a & GDK_HINT_MIN_SIZE) &&
6421       (geometry_a->min_width != geometry_b->min_width ||
6422        geometry_a->min_height != geometry_b->min_height))
6423     return FALSE;
6424
6425   if ((flags_a & GDK_HINT_MAX_SIZE) &&
6426       (geometry_a->max_width != geometry_b->max_width ||
6427        geometry_a->max_height != geometry_b->max_height))
6428     return FALSE;
6429
6430   if ((flags_a & GDK_HINT_BASE_SIZE) &&
6431       (geometry_a->base_width != geometry_b->base_width ||
6432        geometry_a->base_height != geometry_b->base_height))
6433     return FALSE;
6434
6435   if ((flags_a & GDK_HINT_ASPECT) &&
6436       (geometry_a->min_aspect != geometry_b->min_aspect ||
6437        geometry_a->max_aspect != geometry_b->max_aspect))
6438     return FALSE;
6439
6440   if ((flags_a & GDK_HINT_RESIZE_INC) &&
6441       (geometry_a->width_inc != geometry_b->width_inc ||
6442        geometry_a->height_inc != geometry_b->height_inc))
6443     return FALSE;
6444
6445   if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
6446       geometry_a->win_gravity != geometry_b->win_gravity)
6447     return FALSE;
6448
6449   return TRUE;
6450 }
6451
6452 void
6453 _gtk_window_constrain_size (GtkWindow   *window,
6454                             gint         width,
6455                             gint         height,
6456                             gint        *new_width,
6457                             gint        *new_height)
6458 {
6459   GtkWindowGeometryInfo *info;
6460
6461   g_return_if_fail (GTK_IS_WINDOW (window));
6462
6463   info = window->geometry_info;
6464   if (info)
6465     {
6466       GdkWindowHints flags = info->last.flags;
6467       GdkGeometry *geometry = &info->last.geometry;
6468       
6469       gtk_window_constrain_size (window,
6470                                  geometry,
6471                                  flags,
6472                                  width,
6473                                  height,
6474                                  new_width,
6475                                  new_height);
6476     }
6477 }
6478
6479 static void 
6480 gtk_window_constrain_size (GtkWindow   *window,
6481                            GdkGeometry *geometry,
6482                            guint        flags,
6483                            gint         width,
6484                            gint         height,
6485                            gint        *new_width,
6486                            gint        *new_height)
6487 {
6488   gdk_window_constrain_size (geometry, flags, width, height,
6489                              new_width, new_height);
6490 }
6491
6492 /* Compute the set of geometry hints and flags for a window
6493  * based on the application set geometry, and requisiition
6494  * of the window. gtk_widget_size_request() must have been
6495  * called first.
6496  */
6497 static void
6498 gtk_window_compute_hints (GtkWindow   *window,
6499                           GdkGeometry *new_geometry,
6500                           guint       *new_flags)
6501 {
6502   GtkWidget *widget;
6503   gint extra_width = 0;
6504   gint extra_height = 0;
6505   GtkWindowGeometryInfo *geometry_info;
6506   GtkRequisition requisition;
6507
6508   widget = GTK_WIDGET (window);
6509   
6510   gtk_widget_get_child_requisition (widget, &requisition);
6511   geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
6512
6513   if (geometry_info)
6514     {
6515       *new_flags = geometry_info->mask;
6516       *new_geometry = geometry_info->geometry;
6517     }
6518   else
6519     {
6520       *new_flags = 0;
6521     }
6522   
6523   if (geometry_info && geometry_info->widget)
6524     {
6525       GtkRequisition child_requisition;
6526
6527       /* FIXME: This really isn't right. It gets the min size wrong and forces
6528        * callers to do horrible hacks like set a huge usize on the child requisition
6529        * to get the base size right. We really want to find the answers to:
6530        *
6531        *  - If the geometry widget was infinitely big, how much extra space
6532        *    would be needed for the stuff around it.
6533        *
6534        *  - If the geometry widget was infinitely small, how big would the
6535        *    window still have to be.
6536        *
6537        * Finding these answers would be a bit of a mess here. (Bug #68668)
6538        */
6539       gtk_widget_get_child_requisition (geometry_info->widget, &child_requisition);
6540       
6541       extra_width = widget->requisition.width - child_requisition.width;
6542       extra_height = widget->requisition.height - child_requisition.height;
6543     }
6544
6545   /* We don't want to set GDK_HINT_POS in here, we just set it
6546    * in gtk_window_move_resize() when we want the position
6547    * honored.
6548    */
6549   
6550   if (*new_flags & GDK_HINT_BASE_SIZE)
6551     {
6552       new_geometry->base_width += extra_width;
6553       new_geometry->base_height += extra_height;
6554     }
6555   else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
6556            (*new_flags & GDK_HINT_RESIZE_INC) &&
6557            ((extra_width != 0) || (extra_height != 0)))
6558     {
6559       *new_flags |= GDK_HINT_BASE_SIZE;
6560       
6561       new_geometry->base_width = extra_width;
6562       new_geometry->base_height = extra_height;
6563     }
6564   
6565   if (*new_flags & GDK_HINT_MIN_SIZE)
6566     {
6567       if (new_geometry->min_width < 0)
6568         new_geometry->min_width = requisition.width;
6569       else
6570         new_geometry->min_width += extra_width;
6571
6572       if (new_geometry->min_height < 0)
6573         new_geometry->min_height = requisition.height;
6574       else
6575         new_geometry->min_height += extra_height;
6576     }
6577   else if (!window->allow_shrink)
6578     {
6579       *new_flags |= GDK_HINT_MIN_SIZE;
6580       
6581       new_geometry->min_width = requisition.width;
6582       new_geometry->min_height = requisition.height;
6583     }
6584   
6585   if (*new_flags & GDK_HINT_MAX_SIZE)
6586     {
6587       if (new_geometry->max_width < 0)
6588         new_geometry->max_width = requisition.width;
6589       else
6590         new_geometry->max_width += extra_width;
6591
6592       if (new_geometry->max_height < 0)
6593         new_geometry->max_height = requisition.height;
6594       else
6595         new_geometry->max_height += extra_height;
6596     }
6597   else if (!window->allow_grow)
6598     {
6599       *new_flags |= GDK_HINT_MAX_SIZE;
6600       
6601       new_geometry->max_width = requisition.width;
6602       new_geometry->max_height = requisition.height;
6603     }
6604
6605   *new_flags |= GDK_HINT_WIN_GRAVITY;
6606   new_geometry->win_gravity = window->gravity;
6607 }
6608
6609 /***********************
6610  * Redrawing functions *
6611  ***********************/
6612
6613 static void
6614 gtk_window_paint (GtkWidget     *widget,
6615                   GdkRectangle *area)
6616 {
6617   gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL, 
6618                       GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
6619 }
6620
6621 static gint
6622 gtk_window_expose (GtkWidget      *widget,
6623                    GdkEventExpose *event)
6624 {
6625   if (!gtk_widget_get_app_paintable (widget))
6626     gtk_window_paint (widget, &event->area);
6627   
6628   if (GTK_WIDGET_CLASS (gtk_window_parent_class)->expose_event)
6629     return GTK_WIDGET_CLASS (gtk_window_parent_class)->expose_event (widget, event);
6630
6631   return FALSE;
6632 }
6633
6634 /**
6635  * gtk_window_set_has_frame:
6636  * @window: a #GtkWindow
6637  * @setting: a boolean
6638  *
6639  * (Note: this is a special-purpose function for the framebuffer port,
6640  *  that causes GTK+ to draw its own window border. For most applications,
6641  *  you want gtk_window_set_decorated() instead, which tells the window
6642  *  manager whether to draw the window border.)
6643  * 
6644  * If this function is called on a window with setting of %TRUE, before
6645  * it is realized or showed, it will have a "frame" window around
6646  * @window->window, accessible in @window->frame. Using the signal 
6647  * frame_event you can receive all events targeted at the frame.
6648  * 
6649  * This function is used by the linux-fb port to implement managed
6650  * windows, but it could conceivably be used by X-programs that
6651  * want to do their own window decorations.
6652  *
6653  **/
6654 void
6655 gtk_window_set_has_frame (GtkWindow *window, 
6656                           gboolean   setting)
6657 {
6658   g_return_if_fail (GTK_IS_WINDOW (window));
6659   g_return_if_fail (!GTK_WIDGET_REALIZED (window));
6660
6661   window->has_frame = setting != FALSE;
6662 }
6663
6664 /**
6665  * gtk_window_get_has_frame:
6666  * @window: a #GtkWindow
6667  * 
6668  * Accessor for whether the window has a frame window exterior to
6669  * @window->window. Gets the value set by gtk_window_set_has_frame ().
6670  *
6671  * Return value: %TRUE if a frame has been added to the window
6672  *   via gtk_window_set_has_frame().
6673  **/
6674 gboolean
6675 gtk_window_get_has_frame (GtkWindow *window)
6676 {
6677   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
6678
6679   return window->has_frame;
6680 }
6681
6682 /**
6683  * gtk_window_set_frame_dimensions:
6684  * @window: a #GtkWindow that has a frame
6685  * @left: The width of the left border
6686  * @top: The height of the top border
6687  * @right: The width of the right border
6688  * @bottom: The height of the bottom border
6689  *
6690  * (Note: this is a special-purpose function intended for the framebuffer
6691  *  port; see gtk_window_set_has_frame(). It will have no effect on the
6692  *  window border drawn by the window manager, which is the normal
6693  *  case when using the X Window system.)
6694  *
6695  * For windows with frames (see gtk_window_set_has_frame()) this function
6696  * can be used to change the size of the frame border.
6697  **/
6698 void
6699 gtk_window_set_frame_dimensions (GtkWindow *window, 
6700                                  gint       left,
6701                                  gint       top,
6702                                  gint       right,
6703                                  gint       bottom)
6704 {
6705   GtkWidget *widget;
6706
6707   g_return_if_fail (GTK_IS_WINDOW (window));
6708
6709   widget = GTK_WIDGET (window);
6710
6711   if (window->frame_left == left &&
6712       window->frame_top == top &&
6713       window->frame_right == right && 
6714       window->frame_bottom == bottom)
6715     return;
6716
6717   window->frame_left = left;
6718   window->frame_top = top;
6719   window->frame_right = right;
6720   window->frame_bottom = bottom;
6721
6722   if (GTK_WIDGET_REALIZED (widget) && window->frame)
6723     {
6724       gint width = widget->allocation.width + left + right;
6725       gint height = widget->allocation.height + top + bottom;
6726       gdk_window_resize (window->frame, width, height);
6727       gtk_decorated_window_move_resize_window (window,
6728                                                left, top,
6729                                                widget->allocation.width,
6730                                                widget->allocation.height);
6731     }
6732 }
6733
6734 /**
6735  * gtk_window_present:
6736  * @window: a #GtkWindow
6737  *
6738  * Presents a window to the user. This may mean raising the window
6739  * in the stacking order, deiconifying it, moving it to the current
6740  * desktop, and/or giving it the keyboard focus, possibly dependent
6741  * on the user's platform, window manager, and preferences.
6742  *
6743  * If @window is hidden, this function calls gtk_widget_show()
6744  * as well.
6745  * 
6746  * This function should be used when the user tries to open a window
6747  * that's already open. Say for example the preferences dialog is
6748  * currently open, and the user chooses Preferences from the menu
6749  * a second time; use gtk_window_present() to move the already-open dialog
6750  * where the user can see it.
6751  *
6752  * If you are calling this function in response to a user interaction,
6753  * it is preferable to use gtk_window_present_with_time().
6754  * 
6755  **/
6756 void
6757 gtk_window_present (GtkWindow *window)
6758 {
6759   gtk_window_present_with_time (window, GDK_CURRENT_TIME);
6760 }
6761
6762 /**
6763  * gtk_window_present_with_time:
6764  * @window: a #GtkWindow
6765  * @timestamp: the timestamp of the user interaction (typically a 
6766  *   button or key press event) which triggered this call
6767  *
6768  * Presents a window to the user in response to a user interaction.
6769  * If you need to present a window without a timestamp, use 
6770  * gtk_window_present(). See gtk_window_present() for details. 
6771  * 
6772  * Since: 2.8
6773  **/
6774 void
6775 gtk_window_present_with_time (GtkWindow *window,
6776                               guint32    timestamp)
6777 {
6778   GtkWidget *widget;
6779
6780   g_return_if_fail (GTK_IS_WINDOW (window));
6781
6782   widget = GTK_WIDGET (window);
6783
6784   if (gtk_widget_get_visible (widget))
6785     {
6786       g_assert (widget->window != NULL);
6787       
6788       gdk_window_show (widget->window);
6789
6790       /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
6791       if (timestamp == GDK_CURRENT_TIME)
6792         {
6793 #ifdef GDK_WINDOWING_X11
6794           GdkDisplay *display;
6795
6796           display = gtk_widget_get_display (GTK_WIDGET (window));
6797           timestamp = gdk_x11_display_get_user_time (display);
6798 #else
6799           timestamp = gtk_get_current_event_time ();
6800 #endif
6801         }
6802
6803       gdk_window_focus (widget->window, timestamp);
6804     }
6805   else
6806     {
6807       gtk_widget_show (widget);
6808     }
6809 }
6810
6811 /**
6812  * gtk_window_iconify:
6813  * @window: a #GtkWindow
6814  *
6815  * Asks to iconify (i.e. minimize) the specified @window. Note that
6816  * you shouldn't assume the window is definitely iconified afterward,
6817  * because other entities (e.g. the user or <link
6818  * linkend="gtk-X11-arch">window manager</link>) could deiconify it
6819  * again, or there may not be a window manager in which case
6820  * iconification isn't possible, etc. But normally the window will end
6821  * up iconified. Just don't write code that crashes if not.
6822  *
6823  * It's permitted to call this function before showing a window,
6824  * in which case the window will be iconified before it ever appears
6825  * onscreen.
6826  *
6827  * You can track iconification via the "window-state-event" signal
6828  * on #GtkWidget.
6829  * 
6830  **/
6831 void
6832 gtk_window_iconify (GtkWindow *window)
6833 {
6834   GtkWidget *widget;
6835   GdkWindow *toplevel;
6836   
6837   g_return_if_fail (GTK_IS_WINDOW (window));
6838
6839   widget = GTK_WIDGET (window);
6840
6841   window->iconify_initially = TRUE;
6842
6843   if (window->frame)
6844     toplevel = window->frame;
6845   else
6846     toplevel = widget->window;
6847   
6848   if (toplevel != NULL)
6849     gdk_window_iconify (toplevel);
6850 }
6851
6852 /**
6853  * gtk_window_deiconify:
6854  * @window: a #GtkWindow
6855  *
6856  * Asks to deiconify (i.e. unminimize) the specified @window. Note
6857  * that you shouldn't assume the window is definitely deiconified
6858  * afterward, because other entities (e.g. the user or <link
6859  * linkend="gtk-X11-arch">window manager</link>) could iconify it
6860  * again before your code which assumes deiconification gets to run.
6861  *
6862  * You can track iconification via the "window-state-event" signal
6863  * on #GtkWidget.
6864  **/
6865 void
6866 gtk_window_deiconify (GtkWindow *window)
6867 {
6868   GtkWidget *widget;
6869   GdkWindow *toplevel;
6870   
6871   g_return_if_fail (GTK_IS_WINDOW (window));
6872
6873   widget = GTK_WIDGET (window);
6874
6875   window->iconify_initially = FALSE;
6876
6877   if (window->frame)
6878     toplevel = window->frame;
6879   else
6880     toplevel = widget->window;
6881   
6882   if (toplevel != NULL)
6883     gdk_window_deiconify (toplevel);
6884 }
6885
6886 /**
6887  * gtk_window_stick:
6888  * @window: a #GtkWindow
6889  *
6890  * Asks to stick @window, which means that it will appear on all user
6891  * desktops. Note that you shouldn't assume the window is definitely
6892  * stuck afterward, because other entities (e.g. the user or <link
6893  * linkend="gtk-X11-arch">window manager</link>) could unstick it
6894  * again, and some window managers do not support sticking
6895  * windows. But normally the window will end up stuck. Just don't
6896  * write code that crashes if not.
6897  *
6898  * It's permitted to call this function before showing a window.
6899  *
6900  * You can track stickiness via the "window-state-event" signal
6901  * on #GtkWidget.
6902  * 
6903  **/
6904 void
6905 gtk_window_stick (GtkWindow *window)
6906 {
6907   GtkWidget *widget;
6908   GdkWindow *toplevel;
6909   
6910   g_return_if_fail (GTK_IS_WINDOW (window));
6911
6912   widget = GTK_WIDGET (window);
6913
6914   window->stick_initially = TRUE;
6915
6916   if (window->frame)
6917     toplevel = window->frame;
6918   else
6919     toplevel = widget->window;
6920   
6921   if (toplevel != NULL)
6922     gdk_window_stick (toplevel);
6923 }
6924
6925 /**
6926  * gtk_window_unstick:
6927  * @window: a #GtkWindow
6928  *
6929  * Asks to unstick @window, which means that it will appear on only
6930  * one of the user's desktops. Note that you shouldn't assume the
6931  * window is definitely unstuck afterward, because other entities
6932  * (e.g. the user or <link linkend="gtk-X11-arch">window
6933  * manager</link>) could stick it again. But normally the window will
6934  * end up stuck. Just don't write code that crashes if not.
6935  *
6936  * You can track stickiness via the "window-state-event" signal
6937  * on #GtkWidget.
6938  * 
6939  **/
6940 void
6941 gtk_window_unstick (GtkWindow *window)
6942 {
6943   GtkWidget *widget;
6944   GdkWindow *toplevel;
6945   
6946   g_return_if_fail (GTK_IS_WINDOW (window));
6947
6948   widget = GTK_WIDGET (window);
6949
6950   window->stick_initially = FALSE;
6951
6952   if (window->frame)
6953     toplevel = window->frame;
6954   else
6955     toplevel = widget->window;
6956   
6957   if (toplevel != NULL)
6958     gdk_window_unstick (toplevel);
6959 }
6960
6961 /**
6962  * gtk_window_maximize:
6963  * @window: a #GtkWindow
6964  *
6965  * Asks to maximize @window, so that it becomes full-screen. Note that
6966  * you shouldn't assume the window is definitely maximized afterward,
6967  * because other entities (e.g. the user or <link
6968  * linkend="gtk-X11-arch">window manager</link>) could unmaximize it
6969  * again, and not all window managers support maximization. But
6970  * normally the window will end up maximized. Just don't write code
6971  * that crashes if not.
6972  *
6973  * It's permitted to call this function before showing a window,
6974  * in which case the window will be maximized when it appears onscreen
6975  * initially.
6976  *
6977  * You can track maximization via the "window-state-event" signal
6978  * on #GtkWidget.
6979  * 
6980  **/
6981 void
6982 gtk_window_maximize (GtkWindow *window)
6983 {
6984   GtkWidget *widget;
6985   GdkWindow *toplevel;
6986   
6987   g_return_if_fail (GTK_IS_WINDOW (window));
6988
6989   widget = GTK_WIDGET (window);
6990
6991   window->maximize_initially = TRUE;
6992
6993   if (window->frame)
6994     toplevel = window->frame;
6995   else
6996     toplevel = widget->window;
6997   
6998   if (toplevel != NULL)
6999     gdk_window_maximize (toplevel);
7000 }
7001
7002 /**
7003  * gtk_window_unmaximize:
7004  * @window: a #GtkWindow
7005  *
7006  * Asks to unmaximize @window. Note that you shouldn't assume the
7007  * window is definitely unmaximized afterward, because other entities
7008  * (e.g. the user or <link linkend="gtk-X11-arch">window
7009  * manager</link>) could maximize it again, and not all window
7010  * managers honor requests to unmaximize. But normally the window will
7011  * end up unmaximized. Just don't write code that crashes if not.
7012  *
7013  * You can track maximization via the "window-state-event" signal
7014  * on #GtkWidget.
7015  * 
7016  **/
7017 void
7018 gtk_window_unmaximize (GtkWindow *window)
7019 {
7020   GtkWidget *widget;
7021   GdkWindow *toplevel;
7022   
7023   g_return_if_fail (GTK_IS_WINDOW (window));
7024
7025   widget = GTK_WIDGET (window);
7026
7027   window->maximize_initially = FALSE;
7028
7029   if (window->frame)
7030     toplevel = window->frame;
7031   else
7032     toplevel = widget->window;
7033   
7034   if (toplevel != NULL)
7035     gdk_window_unmaximize (toplevel);
7036 }
7037
7038 /**
7039  * gtk_window_fullscreen:
7040  * @window: a #GtkWindow
7041  *
7042  * Asks to place @window in the fullscreen state. Note that you
7043  * shouldn't assume the window is definitely full screen afterward,
7044  * because other entities (e.g. the user or <link
7045  * linkend="gtk-X11-arch">window manager</link>) could unfullscreen it
7046  * again, and not all window managers honor requests to fullscreen
7047  * windows. But normally the window will end up fullscreen. Just
7048  * don't write code that crashes if not.
7049  *
7050  * You can track the fullscreen state via the "window-state-event" signal
7051  * on #GtkWidget.
7052  * 
7053  * Since: 2.2
7054  **/
7055 void
7056 gtk_window_fullscreen (GtkWindow *window)
7057 {
7058   GtkWidget *widget;
7059   GdkWindow *toplevel;
7060   GtkWindowPrivate *priv;
7061   
7062   g_return_if_fail (GTK_IS_WINDOW (window));
7063
7064   widget = GTK_WIDGET (window);
7065   priv = GTK_WINDOW_GET_PRIVATE (window);
7066   
7067   priv->fullscreen_initially = TRUE;
7068
7069   if (window->frame)
7070     toplevel = window->frame;
7071   else
7072     toplevel = widget->window;
7073   
7074   if (toplevel != NULL)
7075     gdk_window_fullscreen (toplevel);
7076 }
7077
7078 /**
7079  * gtk_window_unfullscreen:
7080  * @window: a #GtkWindow
7081  *
7082  * Asks to toggle off the fullscreen state for @window. Note that you
7083  * shouldn't assume the window is definitely not full screen
7084  * afterward, because other entities (e.g. the user or <link
7085  * linkend="gtk-X11-arch">window manager</link>) could fullscreen it
7086  * again, and not all window managers honor requests to unfullscreen
7087  * windows. But normally the window will end up restored to its normal
7088  * state. Just don't write code that crashes if not.
7089  *
7090  * You can track the fullscreen state via the "window-state-event" signal
7091  * on #GtkWidget.
7092  * 
7093  * Since: 2.2
7094  **/
7095 void
7096 gtk_window_unfullscreen (GtkWindow *window)
7097 {
7098   GtkWidget *widget;
7099   GdkWindow *toplevel;
7100   GtkWindowPrivate *priv;
7101   
7102   g_return_if_fail (GTK_IS_WINDOW (window));
7103
7104   widget = GTK_WIDGET (window);
7105   priv = GTK_WINDOW_GET_PRIVATE (window);
7106   
7107   priv->fullscreen_initially = FALSE;
7108
7109   if (window->frame)
7110     toplevel = window->frame;
7111   else
7112     toplevel = widget->window;
7113   
7114   if (toplevel != NULL)
7115     gdk_window_unfullscreen (toplevel);
7116 }
7117
7118 /**
7119  * gtk_window_set_keep_above:
7120  * @window: a #GtkWindow
7121  * @setting: whether to keep @window above other windows
7122  *
7123  * Asks to keep @window above, so that it stays on top. Note that
7124  * you shouldn't assume the window is definitely above afterward,
7125  * because other entities (e.g. the user or <link
7126  * linkend="gtk-X11-arch">window manager</link>) could not keep it above,
7127  * and not all window managers support keeping windows above. But
7128  * normally the window will end kept above. Just don't write code
7129  * that crashes if not.
7130  *
7131  * It's permitted to call this function before showing a window,
7132  * in which case the window will be kept above when it appears onscreen
7133  * initially.
7134  *
7135  * You can track the above state via the "window-state-event" signal
7136  * on #GtkWidget.
7137  *
7138  * Note that, according to the <ulink 
7139  * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window 
7140  * Manager Hints</ulink> specification, the above state is mainly meant 
7141  * for user preferences and should not be used by applications e.g. for 
7142  * drawing attention to their dialogs.
7143  *
7144  * Since: 2.4
7145  **/
7146 void
7147 gtk_window_set_keep_above (GtkWindow *window,
7148                            gboolean   setting)
7149 {
7150   GtkWidget *widget;
7151   GtkWindowPrivate *priv;
7152   GdkWindow *toplevel;
7153
7154   g_return_if_fail (GTK_IS_WINDOW (window));
7155
7156   widget = GTK_WIDGET (window);
7157   priv = GTK_WINDOW_GET_PRIVATE (window);
7158
7159   priv->above_initially = setting != FALSE;
7160   if (setting)
7161     priv->below_initially = FALSE;
7162
7163   if (window->frame)
7164     toplevel = window->frame;
7165   else
7166     toplevel = widget->window;
7167
7168   if (toplevel != NULL)
7169     gdk_window_set_keep_above (toplevel, setting);
7170 }
7171
7172 /**
7173  * gtk_window_set_keep_below:
7174  * @window: a #GtkWindow
7175  * @setting: whether to keep @window below other windows
7176  *
7177  * Asks to keep @window below, so that it stays in bottom. Note that
7178  * you shouldn't assume the window is definitely below afterward,
7179  * because other entities (e.g. the user or <link
7180  * linkend="gtk-X11-arch">window manager</link>) could not keep it below,
7181  * and not all window managers support putting windows below. But
7182  * normally the window will be kept below. Just don't write code
7183  * that crashes if not.
7184  *
7185  * It's permitted to call this function before showing a window,
7186  * in which case the window will be kept below when it appears onscreen
7187  * initially.
7188  *
7189  * You can track the below state via the "window-state-event" signal
7190  * on #GtkWidget.
7191  *
7192  * Note that, according to the <ulink 
7193  * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window 
7194  * Manager Hints</ulink> specification, the above state is mainly meant 
7195  * for user preferences and should not be used by applications e.g. for 
7196  * drawing attention to their dialogs.
7197  *
7198  * Since: 2.4
7199  **/
7200 void
7201 gtk_window_set_keep_below (GtkWindow *window,
7202                            gboolean   setting)
7203 {
7204   GtkWidget *widget;
7205   GtkWindowPrivate *priv;
7206   GdkWindow *toplevel;
7207
7208   g_return_if_fail (GTK_IS_WINDOW (window));
7209
7210   widget = GTK_WIDGET (window);
7211   priv = GTK_WINDOW_GET_PRIVATE (window);
7212
7213   priv->below_initially = setting != FALSE;
7214   if (setting)
7215     priv->above_initially = FALSE;
7216
7217   if (window->frame)
7218     toplevel = window->frame;
7219   else
7220     toplevel = widget->window;
7221
7222   if (toplevel != NULL)
7223     gdk_window_set_keep_below (toplevel, setting);
7224 }
7225
7226 /**
7227  * gtk_window_set_resizable:
7228  * @window: a #GtkWindow
7229  * @resizable: %TRUE if the user can resize this window
7230  *
7231  * Sets whether the user can resize a window. Windows are user resizable
7232  * by default.
7233  **/
7234 void
7235 gtk_window_set_resizable (GtkWindow *window,
7236                           gboolean   resizable)
7237 {
7238   g_return_if_fail (GTK_IS_WINDOW (window));
7239
7240   gtk_window_set_policy_internal (window, FALSE, resizable, FALSE);
7241 }
7242
7243 /**
7244  * gtk_window_get_resizable:
7245  * @window: a #GtkWindow
7246  *
7247  * Gets the value set by gtk_window_set_resizable().
7248  *
7249  * Return value: %TRUE if the user can resize the window
7250  **/
7251 gboolean
7252 gtk_window_get_resizable (GtkWindow *window)
7253 {
7254   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7255
7256   /* allow_grow is most likely to indicate the semantic concept we
7257    * mean by "resizable" (and will be a reliable indicator if
7258    * set_policy() hasn't been called)
7259    */
7260   return window->allow_grow;
7261 }
7262
7263 /**
7264  * gtk_window_set_gravity:
7265  * @window: a #GtkWindow
7266  * @gravity: window gravity
7267  *
7268  * Window gravity defines the meaning of coordinates passed to
7269  * gtk_window_move(). See gtk_window_move() and #GdkGravity for
7270  * more details.
7271  *
7272  * The default window gravity is #GDK_GRAVITY_NORTH_WEST which will
7273  * typically "do what you mean."
7274  *
7275  **/
7276 void
7277 gtk_window_set_gravity (GtkWindow *window,
7278                         GdkGravity gravity)
7279 {
7280   g_return_if_fail (GTK_IS_WINDOW (window));
7281
7282   if (gravity != window->gravity)
7283     {
7284       window->gravity = gravity;
7285
7286       /* gtk_window_move_resize() will adapt gravity
7287        */
7288       gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
7289
7290       g_object_notify (G_OBJECT (window), "gravity");
7291     }
7292 }
7293
7294 /**
7295  * gtk_window_get_gravity:
7296  * @window: a #GtkWindow
7297  *
7298  * Gets the value set by gtk_window_set_gravity().
7299  *
7300  * Return value: (transfer none): window gravity
7301  **/
7302 GdkGravity
7303 gtk_window_get_gravity (GtkWindow *window)
7304 {
7305   g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
7306
7307   return window->gravity;
7308 }
7309
7310 /**
7311  * gtk_window_begin_resize_drag:
7312  * @window: a #GtkWindow
7313  * @button: mouse button that initiated the drag
7314  * @edge: position of the resize control
7315  * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7316  * @root_y: Y position where the user clicked to initiate the drag
7317  * @timestamp: timestamp from the click event that initiated the drag
7318  *
7319  * Starts resizing a window. This function is used if an application
7320  * has window resizing controls. When GDK can support it, the resize
7321  * will be done using the standard mechanism for the <link
7322  * linkend="gtk-X11-arch">window manager</link> or windowing
7323  * system. Otherwise, GDK will try to emulate window resizing,
7324  * potentially not all that well, depending on the windowing system.
7325  * 
7326  **/
7327 void
7328 gtk_window_begin_resize_drag  (GtkWindow    *window,
7329                                GdkWindowEdge edge,
7330                                gint          button,
7331                                gint          root_x,
7332                                gint          root_y,
7333                                guint32       timestamp)
7334 {
7335   GtkWidget *widget;
7336   GdkWindow *toplevel;
7337   
7338   g_return_if_fail (GTK_IS_WINDOW (window));
7339   widget = GTK_WIDGET (window);
7340   g_return_if_fail (gtk_widget_get_visible (widget));
7341   
7342   if (window->frame)
7343     toplevel = window->frame;
7344   else
7345     toplevel = widget->window;
7346   
7347   gdk_window_begin_resize_drag (toplevel,
7348                                 edge, button,
7349                                 root_x, root_y,
7350                                 timestamp);
7351 }
7352
7353 /**
7354  * gtk_window_get_frame_dimensions:
7355  * @window: a #GtkWindow
7356  * @left: (allow-none): location to store the width of the frame at the left, or %NULL
7357  * @top: (allow-none): location to store the height of the frame at the top, or %NULL
7358  * @right: (allow-none): location to store the width of the frame at the returns, or %NULL
7359  * @bottom: (allow-none): location to store the height of the frame at the bottom, or %NULL
7360  *
7361  * (Note: this is a special-purpose function intended for the
7362  *  framebuffer port; see gtk_window_set_has_frame(). It will not
7363  *  return the size of the window border drawn by the <link
7364  *  linkend="gtk-X11-arch">window manager</link>, which is the normal
7365  *  case when using a windowing system.  See
7366  *  gdk_window_get_frame_extents() to get the standard window border
7367  *  extents.)
7368  * 
7369  * Retrieves the dimensions of the frame window for this toplevel.
7370  * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions().
7371  **/
7372 void
7373 gtk_window_get_frame_dimensions (GtkWindow *window,
7374                                  gint      *left,
7375                                  gint      *top,
7376                                  gint      *right,
7377                                  gint      *bottom)
7378 {
7379   g_return_if_fail (GTK_IS_WINDOW (window));
7380
7381   if (left)
7382     *left = window->frame_left;
7383   if (top)
7384     *top = window->frame_top;
7385   if (right)
7386     *right = window->frame_right;
7387   if (bottom)
7388     *bottom = window->frame_bottom;
7389 }
7390
7391 /**
7392  * gtk_window_begin_move_drag:
7393  * @window: a #GtkWindow
7394  * @button: mouse button that initiated the drag
7395  * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
7396  * @root_y: Y position where the user clicked to initiate the drag
7397  * @timestamp: timestamp from the click event that initiated the drag
7398  *
7399  * Starts moving a window. This function is used if an application has
7400  * window movement grips. When GDK can support it, the window movement
7401  * will be done using the standard mechanism for the <link
7402  * linkend="gtk-X11-arch">window manager</link> or windowing
7403  * system. Otherwise, GDK will try to emulate window movement,
7404  * potentially not all that well, depending on the windowing system.
7405  * 
7406  **/
7407 void
7408 gtk_window_begin_move_drag  (GtkWindow *window,
7409                              gint       button,
7410                              gint       root_x,
7411                              gint       root_y,
7412                              guint32    timestamp)
7413 {
7414   GtkWidget *widget;
7415   GdkWindow *toplevel;
7416   
7417   g_return_if_fail (GTK_IS_WINDOW (window));
7418   widget = GTK_WIDGET (window);
7419   g_return_if_fail (gtk_widget_get_visible (widget));
7420   
7421   if (window->frame)
7422     toplevel = window->frame;
7423   else
7424     toplevel = widget->window;
7425   
7426   gdk_window_begin_move_drag (toplevel,
7427                               button,
7428                               root_x, root_y,
7429                               timestamp);
7430 }
7431
7432 /** 
7433  * gtk_window_set_screen:
7434  * @window: a #GtkWindow.
7435  * @screen: a #GdkScreen.
7436  *
7437  * Sets the #GdkScreen where the @window is displayed; if
7438  * the window is already mapped, it will be unmapped, and
7439  * then remapped on the new screen.
7440  *
7441  * Since: 2.2
7442  */
7443 void
7444 gtk_window_set_screen (GtkWindow *window,
7445                        GdkScreen *screen)
7446 {
7447   GtkWidget *widget;
7448   GdkScreen *previous_screen;
7449   gboolean was_mapped;
7450   
7451   g_return_if_fail (GTK_IS_WINDOW (window));
7452   g_return_if_fail (GDK_IS_SCREEN (screen));
7453
7454   if (screen == window->screen)
7455     return;
7456
7457   widget = GTK_WIDGET (window);
7458
7459   previous_screen = window->screen;
7460   was_mapped = gtk_widget_get_mapped (widget);
7461
7462   if (was_mapped)
7463     gtk_widget_unmap (widget);
7464   if (GTK_WIDGET_REALIZED (widget))
7465     gtk_widget_unrealize (widget);
7466       
7467   gtk_window_free_key_hash (window);
7468   window->screen = screen;
7469   gtk_widget_reset_rc_styles (widget);
7470   if (screen != previous_screen)
7471     {
7472       g_signal_handlers_disconnect_by_func (previous_screen,
7473                                             gtk_window_on_composited_changed, window);
7474       g_signal_connect (screen, "composited-changed", 
7475                         G_CALLBACK (gtk_window_on_composited_changed), window);
7476       
7477       _gtk_widget_propagate_screen_changed (widget, previous_screen);
7478       _gtk_widget_propagate_composited_changed (widget);
7479     }
7480   g_object_notify (G_OBJECT (window), "screen");
7481
7482   if (was_mapped)
7483     gtk_widget_map (widget);
7484 }
7485
7486 static void
7487 gtk_window_on_composited_changed (GdkScreen *screen,
7488                                   GtkWindow *window)
7489 {
7490   gtk_widget_queue_draw (GTK_WIDGET (window));
7491   
7492   _gtk_widget_propagate_composited_changed (GTK_WIDGET (window));
7493 }
7494
7495 static GdkScreen *
7496 gtk_window_check_screen (GtkWindow *window)
7497 {
7498   if (window->screen)
7499     return window->screen;
7500   else
7501     {
7502       g_warning ("Screen for GtkWindow not set; you must always set\n"
7503                  "a screen for a GtkWindow before using the window");
7504       return NULL;
7505     }
7506 }
7507
7508 /** 
7509  * gtk_window_get_screen:
7510  * @window: a #GtkWindow.
7511  *
7512  * Returns the #GdkScreen associated with @window.
7513  *
7514  * Return value: (transfer none): a #GdkScreen.
7515  *
7516  * Since: 2.2
7517  */
7518 GdkScreen*
7519 gtk_window_get_screen (GtkWindow *window)
7520 {
7521   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
7522    
7523   return window->screen;
7524 }
7525
7526 /**
7527  * gtk_window_is_active:
7528  * @window: a #GtkWindow
7529  * 
7530  * Returns whether the window is part of the current active toplevel.
7531  * (That is, the toplevel window receiving keystrokes.)
7532  * The return value is %TRUE if the window is active toplevel
7533  * itself, but also if it is, say, a #GtkPlug embedded in the active toplevel.
7534  * You might use this function if you wanted to draw a widget
7535  * differently in an active window from a widget in an inactive window.
7536  * See gtk_window_has_toplevel_focus()
7537  * 
7538  * Return value: %TRUE if the window part of the current active window.
7539  *
7540  * Since: 2.4
7541  **/
7542 gboolean
7543 gtk_window_is_active (GtkWindow *window)
7544 {
7545   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7546
7547   return window->is_active;
7548 }
7549
7550 /**
7551  * gtk_window_has_toplevel_focus:
7552  * @window: a #GtkWindow
7553  * 
7554  * Returns whether the input focus is within this GtkWindow.
7555  * For real toplevel windows, this is identical to gtk_window_is_active(),
7556  * but for embedded windows, like #GtkPlug, the results will differ.
7557  * 
7558  * Return value: %TRUE if the input focus is within this GtkWindow
7559  *
7560  * Since: 2.4
7561  **/
7562 gboolean
7563 gtk_window_has_toplevel_focus (GtkWindow *window)
7564 {
7565   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
7566
7567   return window->has_toplevel_focus;
7568 }
7569
7570 static void
7571 gtk_window_group_class_init (GtkWindowGroupClass *klass)
7572 {
7573 }
7574
7575 GType
7576 gtk_window_group_get_type (void)
7577 {
7578   static GType window_group_type = 0;
7579
7580   if (!window_group_type)
7581     {
7582       const GTypeInfo window_group_info =
7583       {
7584         sizeof (GtkWindowGroupClass),
7585         NULL,           /* base_init */
7586         NULL,           /* base_finalize */
7587         (GClassInitFunc) gtk_window_group_class_init,
7588         NULL,           /* class_finalize */
7589         NULL,           /* class_data */
7590         sizeof (GtkWindowGroup),
7591         0,              /* n_preallocs */
7592         (GInstanceInitFunc) NULL,
7593       };
7594
7595       window_group_type = g_type_register_static (G_TYPE_OBJECT, I_("GtkWindowGroup"), 
7596                                                   &window_group_info, 0);
7597     }
7598
7599   return window_group_type;
7600 }
7601
7602 /**
7603  * gtk_window_group_new:
7604  * 
7605  * Creates a new #GtkWindowGroup object. Grabs added with
7606  * gtk_grab_add() only affect windows within the same #GtkWindowGroup.
7607  * 
7608  * Return value: a new #GtkWindowGroup. 
7609  **/
7610 GtkWindowGroup *
7611 gtk_window_group_new (void)
7612 {
7613   return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
7614 }
7615
7616 static void
7617 window_group_cleanup_grabs (GtkWindowGroup *group,
7618                             GtkWindow      *window)
7619 {
7620   GSList *tmp_list;
7621   GSList *to_remove = NULL;
7622
7623   tmp_list = group->grabs;
7624   while (tmp_list)
7625     {
7626       if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window)
7627         to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
7628       tmp_list = tmp_list->next;
7629     }
7630
7631   while (to_remove)
7632     {
7633       gtk_grab_remove (to_remove->data);
7634       g_object_unref (to_remove->data);
7635       to_remove = g_slist_delete_link (to_remove, to_remove);
7636     }
7637 }
7638
7639 /**
7640  * gtk_window_group_add_window:
7641  * @window_group: a #GtkWindowGroup
7642  * @window: the #GtkWindow to add
7643  * 
7644  * Adds a window to a #GtkWindowGroup. 
7645  **/
7646 void
7647 gtk_window_group_add_window (GtkWindowGroup *window_group,
7648                              GtkWindow      *window)
7649 {
7650   g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
7651   g_return_if_fail (GTK_IS_WINDOW (window));
7652
7653   if (window->group != window_group)
7654     {
7655       g_object_ref (window);
7656       g_object_ref (window_group);
7657       
7658       if (window->group)
7659         gtk_window_group_remove_window (window->group, window);
7660       else
7661         window_group_cleanup_grabs (gtk_window_get_group (NULL), window);
7662
7663       window->group = window_group;
7664
7665       g_object_unref (window);
7666     }
7667 }
7668
7669 /**
7670  * gtk_window_group_remove_window:
7671  * @window_group: a #GtkWindowGroup
7672  * @window: the #GtkWindow to remove
7673  * 
7674  * Removes a window from a #GtkWindowGroup.
7675  **/
7676 void
7677 gtk_window_group_remove_window (GtkWindowGroup *window_group,
7678                                 GtkWindow      *window)
7679 {
7680   g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
7681   g_return_if_fail (GTK_IS_WINDOW (window));
7682   g_return_if_fail (window->group == window_group);
7683
7684   g_object_ref (window);
7685
7686   window_group_cleanup_grabs (window_group, window);
7687   window->group = NULL;
7688   
7689   g_object_unref (window_group);
7690   g_object_unref (window);
7691 }
7692
7693 /**
7694  * gtk_window_group_list_windows:
7695  * @window_group: a #GtkWindowGroup
7696  *
7697  * Returns a list of the #GtkWindows that belong to @window_group.
7698  *
7699  * Returns: (element-type GtkWidget) (transfer container): A newly-allocated list of
7700  *   windows inside the group.
7701  *
7702  * Since: 2.14
7703  **/
7704 GList *
7705 gtk_window_group_list_windows (GtkWindowGroup *window_group)
7706 {
7707   GList *toplevels, *toplevel, *group_windows;
7708
7709   g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL);
7710
7711   group_windows = NULL;
7712   toplevels = gtk_window_list_toplevels ();
7713
7714   for (toplevel = toplevels; toplevel; toplevel = toplevel->next)
7715     {
7716       GtkWindow *window = toplevel->data;
7717
7718       if (window_group == window->group)
7719         group_windows = g_list_prepend (group_windows, window);
7720     }
7721
7722   return g_list_reverse (group_windows);
7723 }
7724
7725 /**
7726  * gtk_window_get_group:
7727  * @window: (allow-none): a #GtkWindow, or %NULL
7728  *
7729  * Returns the group for @window or the default group, if
7730  * @window is %NULL or if @window does not have an explicit
7731  * window group.
7732  *
7733  * Returns: (transfer none): the #GtkWindowGroup for a window or the default group
7734  *
7735  * Since: 2.10
7736  */
7737 GtkWindowGroup *
7738 gtk_window_get_group (GtkWindow *window)
7739 {
7740   if (window && window->group)
7741     return window->group;
7742   else
7743     {
7744       static GtkWindowGroup *default_group = NULL;
7745
7746       if (!default_group)
7747         default_group = gtk_window_group_new ();
7748
7749       return default_group;
7750     }
7751 }
7752
7753 /* Return the current grab widget of the given group 
7754  */
7755 GtkWidget *
7756 _gtk_window_group_get_current_grab (GtkWindowGroup *window_group)
7757 {
7758   if (window_group->grabs)
7759     return GTK_WIDGET (window_group->grabs->data);
7760   return NULL;
7761 }
7762
7763 /*
7764   Derived from XParseGeometry() in XFree86  
7765
7766   Copyright 1985, 1986, 1987,1998  The Open Group
7767
7768   All Rights Reserved.
7769
7770   The above copyright notice and this permission notice shall be included
7771   in all copies or substantial portions of the Software.
7772
7773   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
7774   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
7775   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
7776   IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
7777   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
7778   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
7779   OTHER DEALINGS IN THE SOFTWARE.
7780
7781   Except as contained in this notice, the name of The Open Group shall
7782   not be used in advertising or otherwise to promote the sale, use or
7783   other dealings in this Software without prior written authorization
7784   from The Open Group.
7785 */
7786
7787
7788 /*
7789  *    XParseGeometry parses strings of the form
7790  *   "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
7791  *   width, height, xoffset, and yoffset are unsigned integers.
7792  *   Example:  "=80x24+300-49"
7793  *   The equal sign is optional.
7794  *   It returns a bitmask that indicates which of the four values
7795  *   were actually found in the string.  For each value found,
7796  *   the corresponding argument is updated;  for each value
7797  *   not found, the corresponding argument is left unchanged. 
7798  */
7799
7800 /* The following code is from Xlib, and is minimally modified, so we
7801  * can track any upstream changes if required.  Don't change this
7802  * code. Or if you do, put in a huge comment marking which thing
7803  * changed.
7804  */
7805
7806 static int
7807 read_int (gchar   *string,
7808           gchar  **next)
7809 {
7810   int result = 0;
7811   int sign = 1;
7812   
7813   if (*string == '+')
7814     string++;
7815   else if (*string == '-')
7816     {
7817       string++;
7818       sign = -1;
7819     }
7820
7821   for (; (*string >= '0') && (*string <= '9'); string++)
7822     {
7823       result = (result * 10) + (*string - '0');
7824     }
7825
7826   *next = string;
7827
7828   if (sign >= 0)
7829     return (result);
7830   else
7831     return (-result);
7832 }
7833
7834 /* 
7835  * Bitmask returned by XParseGeometry().  Each bit tells if the corresponding
7836  * value (x, y, width, height) was found in the parsed string.
7837  */
7838 #define NoValue         0x0000
7839 #define XValue          0x0001
7840 #define YValue          0x0002
7841 #define WidthValue      0x0004
7842 #define HeightValue     0x0008
7843 #define AllValues       0x000F
7844 #define XNegative       0x0010
7845 #define YNegative       0x0020
7846
7847 /* Try not to reformat/modify, so we can compare/sync with X sources */
7848 static int
7849 gtk_XParseGeometry (const char   *string,
7850                     int          *x,
7851                     int          *y,
7852                     unsigned int *width,   
7853                     unsigned int *height)  
7854 {
7855   int mask = NoValue;
7856   char *strind;
7857   unsigned int tempWidth, tempHeight;
7858   int tempX, tempY;
7859   char *nextCharacter;
7860
7861   /* These initializations are just to silence gcc */
7862   tempWidth = 0;
7863   tempHeight = 0;
7864   tempX = 0;
7865   tempY = 0;
7866   
7867   if ( (string == NULL) || (*string == '\0')) return(mask);
7868   if (*string == '=')
7869     string++;  /* ignore possible '=' at beg of geometry spec */
7870
7871   strind = (char *)string;
7872   if (*strind != '+' && *strind != '-' && *strind != 'x') {
7873     tempWidth = read_int(strind, &nextCharacter);
7874     if (strind == nextCharacter) 
7875       return (0);
7876     strind = nextCharacter;
7877     mask |= WidthValue;
7878   }
7879
7880   if (*strind == 'x' || *strind == 'X') {       
7881     strind++;
7882     tempHeight = read_int(strind, &nextCharacter);
7883     if (strind == nextCharacter)
7884       return (0);
7885     strind = nextCharacter;
7886     mask |= HeightValue;
7887   }
7888
7889   if ((*strind == '+') || (*strind == '-')) {
7890     if (*strind == '-') {
7891       strind++;
7892       tempX = -read_int(strind, &nextCharacter);
7893       if (strind == nextCharacter)
7894         return (0);
7895       strind = nextCharacter;
7896       mask |= XNegative;
7897
7898     }
7899     else
7900       { strind++;
7901       tempX = read_int(strind, &nextCharacter);
7902       if (strind == nextCharacter)
7903         return(0);
7904       strind = nextCharacter;
7905       }
7906     mask |= XValue;
7907     if ((*strind == '+') || (*strind == '-')) {
7908       if (*strind == '-') {
7909         strind++;
7910         tempY = -read_int(strind, &nextCharacter);
7911         if (strind == nextCharacter)
7912           return(0);
7913         strind = nextCharacter;
7914         mask |= YNegative;
7915
7916       }
7917       else
7918         {
7919           strind++;
7920           tempY = read_int(strind, &nextCharacter);
7921           if (strind == nextCharacter)
7922             return(0);
7923           strind = nextCharacter;
7924         }
7925       mask |= YValue;
7926     }
7927   }
7928         
7929   /* If strind isn't at the end of the string the it's an invalid
7930                 geometry specification. */
7931
7932   if (*strind != '\0') return (0);
7933
7934   if (mask & XValue)
7935     *x = tempX;
7936   if (mask & YValue)
7937     *y = tempY;
7938   if (mask & WidthValue)
7939     *width = tempWidth;
7940   if (mask & HeightValue)
7941     *height = tempHeight;
7942   return (mask);
7943 }
7944
7945 /**
7946  * gtk_window_parse_geometry:
7947  * @window: a #GtkWindow
7948  * @geometry: geometry string
7949  * 
7950  * Parses a standard X Window System geometry string - see the
7951  * manual page for X (type 'man X') for details on this.
7952  * gtk_window_parse_geometry() does work on all GTK+ ports
7953  * including Win32 but is primarily intended for an X environment.
7954  *
7955  * If either a size or a position can be extracted from the
7956  * geometry string, gtk_window_parse_geometry() returns %TRUE
7957  * and calls gtk_window_set_default_size() and/or gtk_window_move()
7958  * to resize/move the window.
7959  *
7960  * If gtk_window_parse_geometry() returns %TRUE, it will also
7961  * set the #GDK_HINT_USER_POS and/or #GDK_HINT_USER_SIZE hints
7962  * indicating to the window manager that the size/position of
7963  * the window was user-specified. This causes most window
7964  * managers to honor the geometry.
7965  *
7966  * Note that for gtk_window_parse_geometry() to work as expected, it has
7967  * to be called when the window has its "final" size, i.e. after calling
7968  * gtk_widget_show_all() on the contents and gtk_window_set_geometry_hints()
7969  * on the window.
7970  * |[
7971  * #include <gtk/gtk.h>
7972  *    
7973  * static void
7974  * fill_with_content (GtkWidget *vbox)
7975  * {
7976  *   /&ast; fill with content... &ast;/
7977  * }
7978  *    
7979  * int
7980  * main (int argc, char *argv[])
7981  * {
7982  *   GtkWidget *window, *vbox;
7983  *   GdkGeometry size_hints = {
7984  *     100, 50, 0, 0, 100, 50, 10, 10, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST  
7985  *   };
7986  *    
7987  *   gtk_init (&argc, &argv);
7988  *   
7989  *   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7990  *   vbox = gtk_vbox_new (FALSE, 0);
7991  *   
7992  *   gtk_container_add (GTK_CONTAINER (window), vbox);
7993  *   fill_with_content (vbox);
7994  *   gtk_widget_show_all (vbox);
7995  *   
7996  *   gtk_window_set_geometry_hints (GTK_WINDOW (window),
7997  *                                  window,
7998  *                                  &size_hints,
7999  *                                  GDK_HINT_MIN_SIZE | 
8000  *                                  GDK_HINT_BASE_SIZE | 
8001  *                                  GDK_HINT_RESIZE_INC);
8002  *   
8003  *   if (argc &gt; 1)
8004  *     {
8005  *       if (!gtk_window_parse_geometry (GTK_WINDOW (window), argv[1]))
8006  *         fprintf (stderr, "Failed to parse '%s'\n", argv[1]);
8007  *     }
8008  *    
8009  *   gtk_widget_show_all (window);
8010  *   gtk_main ();
8011  *    
8012  *   return 0;
8013  * }
8014  * ]|
8015  *
8016  * Return value: %TRUE if string was parsed successfully
8017  **/
8018 gboolean
8019 gtk_window_parse_geometry (GtkWindow   *window,
8020                            const gchar *geometry)
8021 {
8022   gint result, x = 0, y = 0;
8023   guint w, h;
8024   GdkGravity grav;
8025   gboolean size_set, pos_set;
8026   GdkScreen *screen;
8027   
8028   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8029   g_return_val_if_fail (geometry != NULL, FALSE);
8030
8031   screen = gtk_window_check_screen (window);
8032   
8033   result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
8034
8035   size_set = FALSE;
8036   if ((result & WidthValue) || (result & HeightValue))
8037     {
8038       gtk_window_set_default_size_internal (window, 
8039                                             TRUE, result & WidthValue ? w : -1,
8040                                             TRUE, result & HeightValue ? h : -1, 
8041                                             TRUE);
8042       size_set = TRUE;
8043     }
8044
8045   gtk_window_get_size (window, (gint *)&w, (gint *)&h);
8046   
8047   grav = GDK_GRAVITY_NORTH_WEST;
8048
8049   if ((result & XNegative) && (result & YNegative))
8050     grav = GDK_GRAVITY_SOUTH_EAST;
8051   else if (result & XNegative)
8052     grav = GDK_GRAVITY_NORTH_EAST;
8053   else if (result & YNegative)
8054     grav = GDK_GRAVITY_SOUTH_WEST;
8055
8056   if ((result & XValue) == 0)
8057     x = 0;
8058
8059   if ((result & YValue) == 0)
8060     y = 0;
8061
8062   if (grav == GDK_GRAVITY_SOUTH_WEST ||
8063       grav == GDK_GRAVITY_SOUTH_EAST)
8064     y = gdk_screen_get_height (screen) - h + y;
8065
8066   if (grav == GDK_GRAVITY_SOUTH_EAST ||
8067       grav == GDK_GRAVITY_NORTH_EAST)
8068     x = gdk_screen_get_width (screen) - w + x;
8069
8070   /* we don't let you put a window offscreen; maybe some people would
8071    * prefer to be able to, but it's kind of a bogus thing to do.
8072    */
8073   if (y < 0)
8074     y = 0;
8075
8076   if (x < 0)
8077     x = 0;
8078
8079   pos_set = FALSE;
8080   if ((result & XValue) || (result & YValue))
8081     {
8082       gtk_window_set_gravity (window, grav);
8083       gtk_window_move (window, x, y);
8084       pos_set = TRUE;
8085     }
8086
8087   if (size_set || pos_set)
8088     {
8089       /* Set USSize, USPosition hints */
8090       GtkWindowGeometryInfo *info;
8091
8092       info = gtk_window_get_geometry_info (window, TRUE);
8093
8094       if (pos_set)
8095         info->mask |= GDK_HINT_USER_POS;
8096       if (size_set)
8097         info->mask |= GDK_HINT_USER_SIZE;
8098     }
8099   
8100   return result != 0;
8101 }
8102
8103 static void
8104 gtk_window_mnemonic_hash_foreach (guint      keyval,
8105                                   GSList    *targets,
8106                                   gpointer   data)
8107 {
8108   struct {
8109     GtkWindow *window;
8110     GtkWindowKeysForeachFunc func;
8111     gpointer func_data;
8112   } *info = data;
8113
8114   (*info->func) (info->window, keyval, info->window->mnemonic_modifier, TRUE, info->func_data);
8115 }
8116
8117 void
8118 _gtk_window_keys_foreach (GtkWindow                *window,
8119                           GtkWindowKeysForeachFunc func,
8120                           gpointer                 func_data)
8121 {
8122   GSList *groups;
8123   GtkMnemonicHash *mnemonic_hash;
8124
8125   struct {
8126     GtkWindow *window;
8127     GtkWindowKeysForeachFunc func;
8128     gpointer func_data;
8129   } info;
8130
8131   info.window = window;
8132   info.func = func;
8133   info.func_data = func_data;
8134
8135   mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
8136   if (mnemonic_hash)
8137     _gtk_mnemonic_hash_foreach (mnemonic_hash,
8138                                 gtk_window_mnemonic_hash_foreach, &info);
8139
8140   groups = gtk_accel_groups_from_object (G_OBJECT (window));
8141   while (groups)
8142     {
8143       GtkAccelGroup *group = groups->data;
8144       gint i;
8145
8146       for (i = 0; i < group->n_accels; i++)
8147         {
8148           GtkAccelKey *key = &group->priv_accels[i].key;
8149           
8150           if (key->accel_key)
8151             (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
8152         }
8153       
8154       groups = groups->next;
8155     }
8156 }
8157
8158 static void
8159 gtk_window_keys_changed (GtkWindow *window)
8160 {
8161   gtk_window_free_key_hash (window);
8162   gtk_window_get_key_hash (window);
8163 }
8164
8165 typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
8166
8167 struct _GtkWindowKeyEntry
8168 {
8169   guint keyval;
8170   guint modifiers;
8171   guint is_mnemonic : 1;
8172 };
8173
8174 static void 
8175 window_key_entry_destroy (gpointer data)
8176 {
8177   g_slice_free (GtkWindowKeyEntry, data);
8178 }
8179
8180 static void
8181 add_to_key_hash (GtkWindow      *window,
8182                  guint           keyval,
8183                  GdkModifierType modifiers,
8184                  gboolean        is_mnemonic,
8185                  gpointer        data)
8186 {
8187   GtkKeyHash *key_hash = data;
8188
8189   GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
8190
8191   entry->keyval = keyval;
8192   entry->modifiers = modifiers;
8193   entry->is_mnemonic = is_mnemonic;
8194
8195   /* GtkAccelGroup stores lowercased accelerators. To deal
8196    * with this, if <Shift> was specified, uppercase.
8197    */
8198   if (modifiers & GDK_SHIFT_MASK)
8199     {
8200       if (keyval == GDK_Tab)
8201         keyval = GDK_ISO_Left_Tab;
8202       else
8203         keyval = gdk_keyval_to_upper (keyval);
8204     }
8205   
8206   _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
8207 }
8208
8209 static GtkKeyHash *
8210 gtk_window_get_key_hash (GtkWindow *window)
8211 {
8212   GdkScreen *screen = gtk_window_check_screen (window);
8213   GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
8214   
8215   if (key_hash)
8216     return key_hash;
8217   
8218   key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
8219                                 (GDestroyNotify)window_key_entry_destroy);
8220   _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
8221   g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
8222
8223   return key_hash;
8224 }
8225
8226 static void
8227 gtk_window_free_key_hash (GtkWindow *window)
8228 {
8229   GtkKeyHash *key_hash = g_object_get_qdata (G_OBJECT (window), quark_gtk_window_key_hash);
8230   if (key_hash)
8231     {
8232       _gtk_key_hash_free (key_hash);
8233       g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, NULL);
8234     }
8235 }
8236
8237 /**
8238  * gtk_window_activate_key:
8239  * @window:  a #GtkWindow
8240  * @event:   a #GdkEventKey
8241  *
8242  * Activates mnemonics and accelerators for this #GtkWindow. This is normally
8243  * called by the default ::key_press_event handler for toplevel windows,
8244  * however in some cases it may be useful to call this directly when
8245  * overriding the standard key handling for a toplevel window.
8246  *
8247  * Return value: %TRUE if a mnemonic or accelerator was found and activated.
8248  *
8249  * Since: 2.4
8250  */
8251 gboolean
8252 gtk_window_activate_key (GtkWindow   *window,
8253                          GdkEventKey *event)
8254 {
8255   GtkKeyHash *key_hash;
8256   GtkWindowKeyEntry *found_entry = NULL;
8257   gboolean enable_mnemonics;
8258   gboolean enable_accels;
8259
8260   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8261   g_return_val_if_fail (event != NULL, FALSE);
8262
8263   key_hash = gtk_window_get_key_hash (window);
8264
8265   if (key_hash)
8266     {
8267       GSList *tmp_list;
8268       GSList *entries = _gtk_key_hash_lookup (key_hash,
8269                                               event->hardware_keycode,
8270                                               event->state,
8271                                               gtk_accelerator_get_default_mod_mask (),
8272                                               event->group);
8273
8274       g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
8275                     "gtk-enable-mnemonics", &enable_mnemonics,
8276                     "gtk-enable-accels", &enable_accels,
8277                     NULL);
8278
8279       for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
8280         {
8281           GtkWindowKeyEntry *entry = tmp_list->data;
8282           if (entry->is_mnemonic)
8283             {
8284               if (enable_mnemonics)
8285                 {
8286                   found_entry = entry;
8287                   break;
8288                 }
8289             }
8290           else 
8291             {
8292               if (enable_accels && !found_entry)
8293                 {
8294                   found_entry = entry;
8295                 }
8296             }
8297         }
8298
8299       g_slist_free (entries);
8300     }
8301
8302   if (found_entry)
8303     {
8304       if (found_entry->is_mnemonic)
8305         {
8306           if (enable_mnemonics)
8307             return gtk_window_mnemonic_activate (window, found_entry->keyval,
8308                                                  found_entry->modifiers);
8309         }
8310       else
8311         {
8312           if (enable_accels)
8313             return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval,
8314                                               found_entry->modifiers);
8315         }
8316     }
8317
8318   return FALSE;
8319 }
8320
8321 static void
8322 window_update_has_focus (GtkWindow *window)
8323 {
8324   GtkWidget *widget = GTK_WIDGET (window);
8325   gboolean has_focus = window->has_toplevel_focus && window->is_active;
8326   
8327   if (has_focus != window->has_focus)
8328     {
8329       window->has_focus = has_focus;
8330       
8331       if (has_focus)
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, TRUE);       
8337         }
8338       else
8339         {
8340           if (window->focus_widget &&
8341               window->focus_widget != widget &&
8342               gtk_widget_has_focus (window->focus_widget))
8343             do_focus_change (window->focus_widget, FALSE);
8344         }
8345     }
8346 }
8347
8348 /**
8349  * _gtk_window_set_is_active:
8350  * @window: a #GtkWindow
8351  * @is_active: %TRUE if the window is in the currently active toplevel
8352  * 
8353  * Internal function that sets whether the #GtkWindow is part
8354  * of the currently active toplevel window (taking into account inter-process
8355  * embedding.)
8356  **/
8357 void
8358 _gtk_window_set_is_active (GtkWindow *window,
8359                            gboolean   is_active)
8360 {
8361   g_return_if_fail (GTK_IS_WINDOW (window));
8362
8363   is_active = is_active != FALSE;
8364
8365   if (is_active != window->is_active)
8366     {
8367       window->is_active = is_active;
8368       window_update_has_focus (window);
8369
8370       g_object_notify (G_OBJECT (window), "is-active");
8371     }
8372 }
8373
8374 /**
8375  * _gtk_window_set_is_toplevel:
8376  * @window: a #GtkWindow
8377  * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a
8378  * parent of the root window); %FALSE if it is not (for example, for an
8379  * in-process, parented GtkPlug)
8380  *
8381  * Internal function used by #GtkPlug when it gets parented/unparented by a
8382  * #GtkSocket.  This keeps the @window's #GTK_TOPLEVEL flag in sync with the
8383  * global list of toplevel windows.
8384  */
8385 void
8386 _gtk_window_set_is_toplevel (GtkWindow *window,
8387                              gboolean   is_toplevel)
8388 {
8389   if (gtk_widget_is_toplevel (GTK_WIDGET (window)))
8390     g_assert (g_slist_find (toplevel_list, window) != NULL);
8391   else
8392     g_assert (g_slist_find (toplevel_list, window) == NULL);
8393
8394   if (is_toplevel == gtk_widget_is_toplevel (GTK_WIDGET (window)))
8395     return;
8396
8397   if (is_toplevel)
8398     {
8399       GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
8400       toplevel_list = g_slist_prepend (toplevel_list, window);
8401     }
8402   else
8403     {
8404       GTK_WIDGET_UNSET_FLAGS (window, GTK_TOPLEVEL);
8405       toplevel_list = g_slist_remove (toplevel_list, window);
8406     }
8407 }
8408
8409 /**
8410  * _gtk_window_set_has_toplevel_focus:
8411  * @window: a #GtkWindow
8412  * @has_toplevel_focus: %TRUE if the in
8413  * 
8414  * Internal function that sets whether the keyboard focus for the
8415  * toplevel window (taking into account inter-process embedding.)
8416  **/
8417 void
8418 _gtk_window_set_has_toplevel_focus (GtkWindow *window,
8419                                    gboolean   has_toplevel_focus)
8420 {
8421   g_return_if_fail (GTK_IS_WINDOW (window));
8422   
8423   has_toplevel_focus = has_toplevel_focus != FALSE;
8424
8425   if (has_toplevel_focus != window->has_toplevel_focus)
8426     {
8427       window->has_toplevel_focus = has_toplevel_focus;
8428       window_update_has_focus (window);
8429
8430       g_object_notify (G_OBJECT (window), "has-toplevel-focus");
8431     }
8432 }
8433
8434 /**
8435  * gtk_window_set_auto_startup_notification:
8436  * @setting: %TRUE to automatically do startup notification
8437  *
8438  * By default, after showing the first #GtkWindow, GTK+ calls 
8439  * gdk_notify_startup_complete().  Call this function to disable 
8440  * the automatic startup notification. You might do this if your 
8441  * first window is a splash screen, and you want to delay notification 
8442  * until after your real main window has been shown, for example.
8443  *
8444  * In that example, you would disable startup notification
8445  * temporarily, show your splash screen, then re-enable it so that
8446  * showing the main window would automatically result in notification.
8447  * 
8448  * Since: 2.2
8449  **/
8450 void
8451 gtk_window_set_auto_startup_notification (gboolean setting)
8452 {
8453   disable_startup_notification = !setting;
8454 }
8455
8456 /**
8457  * gtk_window_get_window_type:
8458  * @window: a #GtkWindow
8459  *
8460  * Gets the type of the window. See #GtkWindowType.
8461  *
8462  * Return value: the type of the window
8463  *
8464  * Since: 2.20
8465  **/
8466 GtkWindowType
8467 gtk_window_get_window_type (GtkWindow *window)
8468 {
8469   g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL);
8470
8471   return window->type;
8472 }
8473
8474 /* gtk_window_get_mnemonics_visible:
8475  * @window: a #GtkWindow
8476  *
8477  * Gets the value of the #GtkWindow:mnemonics-visible property.
8478  *
8479  * Returns: %TRUE if mnemonics are supposed to be visible
8480  * in this window.
8481  *
8482  * Since: 2.20
8483  */
8484 gboolean
8485 gtk_window_get_mnemonics_visible (GtkWindow *window)
8486 {
8487   GtkWindowPrivate *priv;
8488
8489   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
8490
8491   priv = GTK_WINDOW_GET_PRIVATE (window);
8492
8493   return priv->mnemonics_visible;
8494 }
8495
8496 /**
8497  * gtk_window_set_mnemonics_visible:
8498  * @window: a #GtkWindow
8499  * @setting: the new value
8500  *
8501  * Sets the #GtkWindow:mnemonics-visible property.
8502  *
8503  * Since: 2.20
8504  */
8505 void
8506 gtk_window_set_mnemonics_visible (GtkWindow *window,
8507                                   gboolean   setting)
8508 {
8509   GtkWindowPrivate *priv;
8510
8511   g_return_if_fail (GTK_IS_WINDOW (window));
8512
8513   priv = GTK_WINDOW_GET_PRIVATE (window);
8514
8515   setting = setting != FALSE;
8516
8517   if (priv->mnemonics_visible != setting)
8518     {
8519       priv->mnemonics_visible = setting;
8520       g_object_notify (G_OBJECT (window), "mnemonics-visible");
8521     }
8522
8523   priv->mnemonics_visible_set = TRUE;
8524 }
8525
8526 #if defined (G_OS_WIN32) && !defined (_WIN64)
8527
8528 #undef gtk_window_set_icon_from_file
8529
8530 gboolean
8531 gtk_window_set_icon_from_file (GtkWindow   *window,
8532                                const gchar *filename,
8533                                GError     **err)
8534 {
8535   gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, err);
8536   gboolean retval;
8537
8538   if (utf8_filename == NULL)
8539     return FALSE;
8540
8541   retval = gtk_window_set_icon_from_file_utf8 (window, utf8_filename, err);
8542
8543   g_free (utf8_filename);
8544
8545   return retval;
8546 }
8547
8548 #undef gtk_window_set_default_icon_from_file
8549
8550 gboolean
8551 gtk_window_set_default_icon_from_file (const gchar *filename,
8552                                        GError     **err)
8553 {
8554   gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, err);
8555   gboolean retval;
8556
8557   if (utf8_filename == NULL)
8558     return FALSE;
8559
8560   retval = gtk_window_set_default_icon_from_file_utf8 (utf8_filename, err);
8561
8562   g_free (utf8_filename);
8563
8564   return retval;
8565 }
8566
8567 #endif
8568
8569 #define __GTK_WINDOW_C__
8570 #include "gtkaliasdef.c"