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