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