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