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