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