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