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